|
|
|
|
@@ -9,7 +9,9 @@ const MAX_DOMAIN_LENGTH = 16;
|
|
|
|
|
|
|
|
|
|
// DualAuth ByteBuddy Agent (runtime class transformation, no JAR modification)
|
|
|
|
|
const DUALAUTH_AGENT_URL = 'https://github.com/sanasol/hytale-auth-server/releases/latest/download/dualauth-agent.jar';
|
|
|
|
|
const DUALAUTH_AGENT_VERSION_API = 'https://api.github.com/repos/sanasol/hytale-auth-server/releases/latest';
|
|
|
|
|
const DUALAUTH_AGENT_FILENAME = 'dualauth-agent.jar';
|
|
|
|
|
const DUALAUTH_AGENT_VERSION_FILE = 'dualauth-agent.version';
|
|
|
|
|
|
|
|
|
|
function getTargetDomain() {
|
|
|
|
|
if (process.env.HYTALE_AUTH_DOMAIN) {
|
|
|
|
|
@@ -511,30 +513,70 @@ class ClientPatcher {
|
|
|
|
|
*/
|
|
|
|
|
async ensureAgentAvailable(serverDir, progressCallback) {
|
|
|
|
|
const agentPath = this.getAgentPath(serverDir);
|
|
|
|
|
const versionPath = path.join(serverDir, DUALAUTH_AGENT_VERSION_FILE);
|
|
|
|
|
|
|
|
|
|
console.log('=== DualAuth Agent (ByteBuddy) ===');
|
|
|
|
|
console.log(`Target: ${agentPath}`);
|
|
|
|
|
|
|
|
|
|
// Check if agent already exists and is valid
|
|
|
|
|
// Check local version and whether file exists
|
|
|
|
|
let localVersion = null;
|
|
|
|
|
let agentExists = false;
|
|
|
|
|
if (fs.existsSync(agentPath)) {
|
|
|
|
|
try {
|
|
|
|
|
const stats = fs.statSync(agentPath);
|
|
|
|
|
if (stats.size > 1024) {
|
|
|
|
|
console.log(`DualAuth Agent present (${(stats.size / 1024).toFixed(0)} KB)`);
|
|
|
|
|
if (progressCallback) progressCallback('DualAuth Agent ready', 100);
|
|
|
|
|
return { success: true, agentPath, alreadyExists: true };
|
|
|
|
|
agentExists = true;
|
|
|
|
|
if (fs.existsSync(versionPath)) {
|
|
|
|
|
localVersion = fs.readFileSync(versionPath, 'utf8').trim();
|
|
|
|
|
}
|
|
|
|
|
// File exists but too small - corrupt, re-download
|
|
|
|
|
} else {
|
|
|
|
|
console.log('Agent file appears corrupt, re-downloading...');
|
|
|
|
|
fs.unlinkSync(agentPath);
|
|
|
|
|
}
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.warn('Could not check agent file:', e.message);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check for updates from GitHub
|
|
|
|
|
let remoteVersion = null;
|
|
|
|
|
let needsDownload = !agentExists;
|
|
|
|
|
if (agentExists) {
|
|
|
|
|
try {
|
|
|
|
|
if (progressCallback) progressCallback('Checking for agent updates...', 5);
|
|
|
|
|
const axios = require('axios');
|
|
|
|
|
const resp = await axios.get(DUALAUTH_AGENT_VERSION_API, {
|
|
|
|
|
timeout: 5000,
|
|
|
|
|
headers: { 'Accept': 'application/vnd.github.v3+json' }
|
|
|
|
|
});
|
|
|
|
|
remoteVersion = resp.data.tag_name; // e.g. "v1.1.10"
|
|
|
|
|
if (localVersion && localVersion === remoteVersion) {
|
|
|
|
|
console.log(`DualAuth Agent up to date (${localVersion})`);
|
|
|
|
|
if (progressCallback) progressCallback('DualAuth Agent ready', 100);
|
|
|
|
|
return { success: true, agentPath, alreadyExists: true, version: localVersion };
|
|
|
|
|
}
|
|
|
|
|
console.log(`Agent update available: ${localVersion || 'unknown'} → ${remoteVersion}`);
|
|
|
|
|
needsDownload = true;
|
|
|
|
|
} catch (e) {
|
|
|
|
|
// GitHub API failed - use existing agent if available
|
|
|
|
|
console.warn(`Could not check for updates: ${e.message}`);
|
|
|
|
|
if (agentExists) {
|
|
|
|
|
console.log(`Using existing agent (${localVersion || 'unknown version'})`);
|
|
|
|
|
if (progressCallback) progressCallback('DualAuth Agent ready', 100);
|
|
|
|
|
return { success: true, agentPath, alreadyExists: true, version: localVersion };
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!needsDownload) {
|
|
|
|
|
if (progressCallback) progressCallback('DualAuth Agent ready', 100);
|
|
|
|
|
return { success: true, agentPath, alreadyExists: true, version: localVersion };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Download agent from GitHub releases
|
|
|
|
|
if (progressCallback) progressCallback('Downloading DualAuth Agent...', 20);
|
|
|
|
|
console.log(`Downloading from: ${DUALAUTH_AGENT_URL}`);
|
|
|
|
|
const action = agentExists ? 'Updating' : 'Downloading';
|
|
|
|
|
if (progressCallback) progressCallback(`${action} DualAuth Agent...`, 20);
|
|
|
|
|
console.log(`${action} from: ${DUALAUTH_AGENT_URL}`);
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
// Ensure server directory exists
|
|
|
|
|
@@ -548,7 +590,7 @@ class ClientPatcher {
|
|
|
|
|
const stream = await smartDownloadStream(DUALAUTH_AGENT_URL, (chunk, downloadedBytes, total) => {
|
|
|
|
|
if (progressCallback && total) {
|
|
|
|
|
const percent = 20 + Math.floor((downloadedBytes / total) * 70);
|
|
|
|
|
progressCallback(`Downloading agent... ${(downloadedBytes / 1024).toFixed(0)} KB`, percent);
|
|
|
|
|
progressCallback(`${action} agent... ${(downloadedBytes / 1024).toFixed(0)} KB`, percent);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
@@ -575,9 +617,13 @@ class ClientPatcher {
|
|
|
|
|
}
|
|
|
|
|
fs.renameSync(tmpPath, agentPath);
|
|
|
|
|
|
|
|
|
|
console.log(`DualAuth Agent downloaded (${(stats.size / 1024).toFixed(0)} KB)`);
|
|
|
|
|
// Save version
|
|
|
|
|
const version = remoteVersion || 'unknown';
|
|
|
|
|
fs.writeFileSync(versionPath, version, 'utf8');
|
|
|
|
|
|
|
|
|
|
console.log(`DualAuth Agent ${agentExists ? 'updated' : 'downloaded'} (${(stats.size / 1024).toFixed(0)} KB, ${version})`);
|
|
|
|
|
if (progressCallback) progressCallback('DualAuth Agent ready', 100);
|
|
|
|
|
return { success: true, agentPath };
|
|
|
|
|
return { success: true, agentPath, updated: agentExists, version };
|
|
|
|
|
|
|
|
|
|
} catch (downloadError) {
|
|
|
|
|
console.error(`Failed to download DualAuth Agent: ${downloadError.message}`);
|
|
|
|
|
@@ -586,6 +632,11 @@ class ClientPatcher {
|
|
|
|
|
if (fs.existsSync(tmpPath)) {
|
|
|
|
|
try { fs.unlinkSync(tmpPath); } catch (e) { /* ignore */ }
|
|
|
|
|
}
|
|
|
|
|
// If we had an existing agent, still use it
|
|
|
|
|
if (agentExists) {
|
|
|
|
|
console.log('Using existing agent despite update failure');
|
|
|
|
|
return { success: true, agentPath, alreadyExists: true, version: localVersion };
|
|
|
|
|
}
|
|
|
|
|
return { success: false, error: downloadError.message };
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|