const fsp = require('fs').promises; const { validateConfig } = require('../../config-schema'); const { exists } = require('../../fs-helpers'); module.exports = function(ctx) { const express = require('express'); const router = express.Router(); // ===== DASHCADDY CONFIG ENDPOINTS ===== // Server-side config storage for setup wizard (shared across all browsers/machines) router.get('/config', ctx.asyncHandler(async (req, res) => { if (!await exists(ctx.CONFIG_FILE)) { return res.json({ setupComplete: false }); } const data = await fsp.readFile(ctx.CONFIG_FILE, 'utf8'); const config = JSON.parse(data); res.json(config); }, 'config-get')); router.post('/config', ctx.asyncHandler(async (req, res) => { const incoming = req.body; if (!incoming || typeof incoming !== 'object') { return ctx.errorResponse(res, 400, 'Invalid config object'); } // Merge with existing config so partial saves don't wipe fields let existing = {}; if (await exists(ctx.CONFIG_FILE)) { try { existing = JSON.parse(await fsp.readFile(ctx.CONFIG_FILE, 'utf8')); } catch (_) { /* start fresh if file is corrupt */ } } const config = { ...existing, ...incoming }; // Merge nested dns object so partial dns updates don't wipe dns fields if (existing.dns && incoming.dns) { config.dns = { ...existing.dns, ...incoming.dns }; } // Merge nested dnsServers object if (existing.dnsServers && incoming.dnsServers) { config.dnsServers = { ...existing.dnsServers, ...incoming.dnsServers }; } // Validate merged config against schema const { valid, errors, warnings } = validateConfig(config); if (!valid) { return ctx.errorResponse(res, 400, 'Config validation failed', { errors }); } // Add timestamp config.updatedAt = new Date().toISOString(); await fsp.writeFile(ctx.CONFIG_FILE, JSON.stringify(config, null, 2), 'utf8'); ctx.loadSiteConfig(); // Refresh in-memory config ctx.log.info('config', 'Config saved', { path: ctx.CONFIG_FILE }); res.json({ success: true, message: 'Configuration saved', config, warnings }); }, 'config-save')); router.delete('/config', ctx.asyncHandler(async (req, res) => { if (await exists(ctx.CONFIG_FILE)) { await fsp.unlink(ctx.CONFIG_FILE); } res.json({ success: true, message: 'Configuration reset' }); }, 'config-delete')); return router; };