Sync DNS2 production changes - removed obsolete test suite and refactored structure

This commit is contained in:
Krystie
2026-03-23 10:47:15 +01:00
parent 1ac50918ab
commit d76644d948
288 changed files with 8965 additions and 15731 deletions

View File

@@ -56,7 +56,7 @@ module.exports = function(ctx) {
res.json({
success: true,
path: `/assets/${safeFilename}`,
message: `Logo saved to ${filePath}`,
message: `Logo saved to ${filePath}`
});
}, 'assets-upload'));
@@ -75,7 +75,7 @@ module.exports = function(ctx) {
customLogo: config.customLogo || config.customLogoDark || null,
position: config.logoPosition || 'left',
dashboardTitle: config.dashboardTitle || 'DashCaddy',
isDefault: !config.customLogoDark && !config.customLogoLight && !config.customLogo,
isDefault: !config.customLogoDark && !config.customLogoLight && !config.customLogo
});
}, 'logo-get'));
@@ -153,7 +153,7 @@ module.exports = function(ctx) {
path: pathDark || pathLight,
position: config.logoPosition || 'left',
dashboardTitle: config.dashboardTitle || 'DashCaddy',
message: 'Branding settings saved',
message: 'Branding settings saved'
});
}, 'logo-upload'));
@@ -186,7 +186,7 @@ module.exports = function(ctx) {
res.json({
success: true,
message: 'Branding reset to defaults',
message: 'Branding reset to defaults'
});
}, 'logo-delete'));
@@ -199,7 +199,7 @@ module.exports = function(ctx) {
res.json({
success: true,
customFavicon: config.customFavicon || null,
isDefault: !config.customFavicon,
isDefault: !config.customFavicon
});
}, 'favicon-get'));
@@ -237,8 +237,8 @@ module.exports = function(ctx) {
sharp(buffer)
.resize(size, size, { fit: 'contain', background: { r: 0, g: 0, b: 0, alpha: 0 } })
.png()
.toBuffer(),
),
.toBuffer()
)
);
// Convert to ICO
@@ -261,7 +261,7 @@ module.exports = function(ctx) {
res.json({
success: true,
path: '/assets/favicon.ico',
message: 'Favicon created successfully',
message: 'Favicon created successfully'
});
}, 'favicon'));
@@ -285,7 +285,7 @@ module.exports = function(ctx) {
res.json({
success: true,
message: 'Favicon reset to default',
message: 'Favicon reset to default'
});
}, 'favicon-delete'));

View File

@@ -34,7 +34,7 @@ module.exports = function(ctx) {
dashcaddyVersion: '1.0.0',
files: {},
themes: {},
assets: {},
assets: {}
};
// Collect all configuration files (encryption key now included for self-contained restore)
@@ -48,7 +48,7 @@ module.exports = function(ctx) {
{ key: 'encryptionKey', path: ENCRYPTION_KEY_FILE, required: false },
{ key: 'totpConfig', path: ctx.TOTP_CONFIG_FILE, required: false },
{ key: 'tailscaleConfig', path: ctx.TAILSCALE_CONFIG_FILE, required: false },
{ key: 'notifications', path: ctx.NOTIFICATIONS_FILE, required: false },
{ key: 'notifications', path: ctx.NOTIFICATIONS_FILE, required: false }
];
for (const file of filesToBackup) {
@@ -59,12 +59,12 @@ module.exports = function(ctx) {
try {
backup.files[file.key] = {
type: 'json',
data: JSON.parse(content),
data: JSON.parse(content)
};
} catch {
backup.files[file.key] = {
type: 'text',
data: content,
data: content
};
}
} else if (file.required) {
@@ -85,7 +85,7 @@ module.exports = function(ctx) {
const otpauth = authenticator.keyuri('user', 'DashCaddy', secret);
const qrDataUrl = await QRCode.toDataURL(otpauth, {
width: 256, margin: 2,
color: { dark: '#000000', light: '#ffffff' },
color: { dark: '#000000', light: '#ffffff' }
});
backup.totp = { qrCode: qrDataUrl, issuer: 'DashCaddy' };
}
@@ -140,7 +140,7 @@ module.exports = function(ctx) {
valid: true,
version: backup.version,
exportedAt: backup.exportedAt,
files: {},
files: {}
};
// Check each file in the backup
@@ -154,7 +154,7 @@ module.exports = function(ctx) {
encryptionKey: { path: ENCRYPTION_KEY_FILE, description: 'Encryption key (for credentials)' },
totpConfig: { path: ctx.TOTP_CONFIG_FILE, description: 'TOTP authentication config' },
tailscaleConfig: { path: ctx.TAILSCALE_CONFIG_FILE, description: 'Tailscale config' },
notifications: { path: ctx.NOTIFICATIONS_FILE, description: 'Notification settings' },
notifications: { path: ctx.NOTIFICATIONS_FILE, description: 'Notification settings' }
};
for (const [key, value] of Object.entries(backup.files)) {
@@ -167,7 +167,7 @@ module.exports = function(ctx) {
inBackup: true,
currentExists,
action: currentExists ? 'overwrite' : 'create',
type: value.type,
type: value.type
};
}
}
@@ -204,7 +204,7 @@ module.exports = function(ctx) {
// Require TOTP verification for restores that include security-sensitive files
const sensitiveKeys = ['credentials', 'totpConfig', 'encryptionKey'];
const restoresSensitive = sensitiveKeys.some(key =>
backup.files[key] && backup.files[key].type !== 'missing' && !(options.skip || []).includes(key),
backup.files[key] && backup.files[key].type !== 'missing' && !(options.skip || []).includes(key)
);
if (restoresSensitive && ctx.totpConfig.enabled && ctx.totpConfig.isSetUp) {
if (!totpCode || !/^\d{6}$/.test(totpCode)) {
@@ -223,7 +223,7 @@ module.exports = function(ctx) {
const results = {
restored: [],
skipped: [],
errors: [],
errors: []
};
const ENCRYPTION_KEY_FILE = process.env.ENCRYPTION_KEY_FILE || path.join(path.dirname(ctx.SERVICES_FILE), '.encryption-key');
@@ -236,7 +236,7 @@ module.exports = function(ctx) {
encryptionKey: ENCRYPTION_KEY_FILE,
totpConfig: ctx.TOTP_CONFIG_FILE,
tailscaleConfig: ctx.TAILSCALE_CONFIG_FILE,
notifications: ctx.NOTIFICATIONS_FILE,
notifications: ctx.NOTIFICATIONS_FILE
};
// Restore each file
@@ -286,7 +286,7 @@ module.exports = function(ctx) {
const loadResponse = await ctx.fetchT(`${ctx.caddy.adminUrl}/load`, {
method: 'POST',
headers: { 'Content-Type': CADDY.CONTENT_TYPE },
body: caddyContent,
body: caddyContent
});
if (loadResponse.ok) {
@@ -345,7 +345,7 @@ module.exports = function(ctx) {
if (!fs.existsSync(THEMES_DIR)) fs.mkdirSync(THEMES_DIR, { recursive: true });
for (const [slug, data] of Object.entries(backup.themes)) {
if (/^[a-z0-9-]+$/.test(slug)) {
fs.writeFileSync(path.join(THEMES_DIR, `${slug }.json`), JSON.stringify(data, null, 2), 'utf8');
fs.writeFileSync(path.join(THEMES_DIR, slug + '.json'), JSON.stringify(data, null, 2), 'utf8');
}
}
results.restored.push(`themes:${Object.keys(backup.themes).length}`);
@@ -376,7 +376,7 @@ module.exports = function(ctx) {
message: success
? `Restored ${results.restored.length} file(s) successfully`
: `Restore completed with ${results.errors.length} error(s)`,
results,
results
});
ctx.log.info('backup', 'Backup restore completed', { restored: results.restored.length, errors: results.errors.length });