/** * Handlers for backup create, list, restore, delete. * Context: backupManager, holesailManager, setTunnelsRestoredPromise, restorePersistedTunnels, log */ const rateLimit = require('../rate-limit.js'); function register(deps) { const { backupManager, holesailManager, setTunnelsRestoredPromise, restorePersistedTunnels, log } = deps; return [ { type: 'createBackup', handle: async (payload, reply) => { const rl = rateLimit.check('createBackup'); if (!rl.allowed) { reply({ ok: false, error: rl.error }); return; } const backupResult = await backupManager.createBackup(); if (backupResult.ok) { const retention = (holesailManager.getSettings().backupRetention) || backupManager.DEFAULT_RETENTION; backupManager.pruneOldBackups(retention); } reply(backupResult); } }, { type: 'listBackups', handle: async (payload, reply) => reply(backupManager.listBackups()) }, { type: 'restoreBackup', handle: async (payload, reply) => { const rl = rateLimit.check('restoreBackup'); if (!rl.allowed) { reply({ ok: false, error: rl.error }); return; } const restoreResult = await backupManager.restoreBackup(payload.filename); if (restoreResult.ok) { await holesailManager.cleanup().catch(() => {}); const restored = holesailManager.restorePersistedState(); setTunnelsRestoredPromise( restorePersistedTunnels(holesailManager, restored).catch((e) => log('Post-restore tunnel start failed:', e.message)) ); } reply(restoreResult); } }, { type: 'deleteBackup', handle: async (payload, reply) => { const rl = rateLimit.check('deleteBackup'); if (!rl.allowed) { reply({ ok: false, error: rl.error }); return; } reply(backupManager.deleteBackup(payload.filename)); } } ]; } module.exports = { register };