Refactor config routes: explicit dependency injection
- Updated all config route modules to use destructured dependencies - Added JSDoc comments for factory functions - Replaced ctx. references with direct parameter access - All files pass syntax validation Files refactored: - routes/config/assets.js - routes/config/backup.js - routes/config/settings.js - routes/config/index.js (orchestrator)
This commit is contained in:
@@ -5,8 +5,17 @@ const { CADDY } = require('../../constants');
|
||||
const { exists } = require('../../fs-helpers');
|
||||
const { ValidationError, AuthenticationError } = require('../errors');
|
||||
|
||||
module.exports = function(ctx) {
|
||||
module.exports = function({ configStateManager, servicesStateManager, asyncHandler, log }) {
|
||||
const express = require('express');
|
||||
/**
|
||||
* Config backup routes factory
|
||||
* @param {Object} deps - Explicit dependencies
|
||||
* @param {Object} deps.configStateManager - Config state manager
|
||||
* @param {Object} deps.servicesStateManager - Services state manager
|
||||
* @param {Function} deps.asyncHandler - Async route handler wrapper
|
||||
* @param {Object} deps.log - Logger instance
|
||||
* @returns {express.Router}
|
||||
*/
|
||||
const router = express.Router();
|
||||
|
||||
const THEMES_DIR = process.env.THEMES_DIR || path.join(path.dirname(ctx.SERVICES_FILE), 'themes');
|
||||
@@ -28,7 +37,7 @@ module.exports = function(ctx) {
|
||||
// Unified v2.0 backup — server config + encryption key + themes (browser state added client-side)
|
||||
|
||||
// Export all configuration as a downloadable JSON bundle
|
||||
router.get('/backup/export', ctx.asyncHandler(async (req, res) => {
|
||||
router.get('/backup/export', asyncHandler(async (req, res) => {
|
||||
const backup = {
|
||||
version: '2.0',
|
||||
exportedAt: new Date().toISOString(),
|
||||
@@ -72,7 +81,7 @@ module.exports = function(ctx) {
|
||||
backup.files[file.key] = { type: 'missing', data: null };
|
||||
}
|
||||
} catch (e) {
|
||||
ctx.log.warn('backup', `Could not backup ${file.key}`, { error: e.message });
|
||||
log.warn('backup', `Could not backup ${file.key}`, { error: e.message });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,7 +100,7 @@ module.exports = function(ctx) {
|
||||
backup.totp = { qrCode: qrDataUrl, issuer: 'DashCaddy' };
|
||||
}
|
||||
} catch (e) {
|
||||
ctx.log.warn('backup', 'Could not include TOTP QR in backup', { error: e.message });
|
||||
log.warn('backup', 'Could not include TOTP QR in backup', { error: e.message });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,14 +119,14 @@ module.exports = function(ctx) {
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
ctx.log.warn('backup', 'Could not include assets in backup', { error: e.message });
|
||||
log.warn('backup', 'Could not include assets in backup', { error: e.message });
|
||||
}
|
||||
|
||||
// Include user-created themes
|
||||
try {
|
||||
backup.themes = readAllThemes();
|
||||
} catch (e) {
|
||||
ctx.log.warn('backup', 'Could not include themes in backup', { error: e.message });
|
||||
log.warn('backup', 'Could not include themes in backup', { error: e.message });
|
||||
}
|
||||
|
||||
// Set headers for file download
|
||||
@@ -126,11 +135,11 @@ module.exports = function(ctx) {
|
||||
res.setHeader('Content-Disposition', `attachment; filename="${backupFilename}"`);
|
||||
|
||||
res.json(backup);
|
||||
ctx.log.info('backup', 'Backup exported successfully');
|
||||
log.info('backup', 'Backup exported successfully');
|
||||
}, 'backup-export'));
|
||||
|
||||
// Preview what will be restored (without making changes)
|
||||
router.post('/backup/preview', ctx.asyncHandler(async (req, res) => {
|
||||
router.post('/backup/preview', asyncHandler(async (req, res) => {
|
||||
const backup = req.body;
|
||||
|
||||
if (!backup || !backup.version || !backup.files) {
|
||||
@@ -195,7 +204,7 @@ module.exports = function(ctx) {
|
||||
}, 'backup-preview'));
|
||||
|
||||
// Restore configuration from backup
|
||||
router.post('/backup/restore', ctx.asyncHandler(async (req, res) => {
|
||||
router.post('/backup/restore', asyncHandler(async (req, res) => {
|
||||
const { backup, options = {}, totpCode } = req.body;
|
||||
|
||||
if (!backup || !backup.version || !backup.files) {
|
||||
@@ -274,7 +283,7 @@ module.exports = function(ctx) {
|
||||
|
||||
await fsp.writeFile(filePath, content, 'utf8');
|
||||
results.restored.push(key);
|
||||
ctx.log.info('backup', `Restored: ${key}`, { path: filePath });
|
||||
log.info('backup', `Restored: ${key}`, { path: filePath });
|
||||
} catch (e) {
|
||||
results.errors.push({ file: key, error: e.message });
|
||||
}
|
||||
@@ -350,7 +359,7 @@ module.exports = function(ctx) {
|
||||
}
|
||||
}
|
||||
results.restored.push(`themes:${Object.keys(backup.themes).length}`);
|
||||
ctx.log.info('backup', `Restored ${Object.keys(backup.themes).length} themes`);
|
||||
log.info('backup', `Restored ${Object.keys(backup.themes).length} themes`);
|
||||
} catch (e) {
|
||||
results.errors.push({ file: 'themes', error: e.message });
|
||||
}
|
||||
@@ -366,7 +375,7 @@ module.exports = function(ctx) {
|
||||
}
|
||||
results.encryptionKeyReloaded = true;
|
||||
} catch (e) {
|
||||
ctx.log.warn('backup', 'Could not reload encryption key', { error: e.message });
|
||||
log.warn('backup', 'Could not reload encryption key', { error: e.message });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -380,7 +389,7 @@ module.exports = function(ctx) {
|
||||
results
|
||||
});
|
||||
|
||||
ctx.log.info('backup', 'Backup restore completed', { restored: results.restored.length, errors: results.errors.length });
|
||||
log.info('backup', 'Backup restore completed', { restored: results.restored.length, errors: results.errors.length });
|
||||
}, 'backup-restore'));
|
||||
|
||||
return router;
|
||||
|
||||
Reference in New Issue
Block a user