const path = require('path'); const fs = require('fs'); const { runBackup, listBackups, BACKUP_DIR, BACKUP_FILENAME_RE } = require('../utils/backupUtils'); const { safeErrorMessage } = require('../utils/errorUtils'); // @desc List local database backups (newest first) // @route GET /api/backups // @access Admin const getBackups = async (req, res) => { try { const backups = await listBackups(); res.json(backups); } catch (e) { res.status(500).json({ message: safeErrorMessage(e) }); } }; // @desc Manually trigger a backup now // @route POST /api/backups/run // @access Admin const triggerBackup = async (req, res) => { try { const result = await runBackup(); res.status(201).json(result); } catch (e) { res.status(500).json({ message: safeErrorMessage(e) }); } }; // @desc Download a backup file // @route GET /api/backups/:filename/download // @access Admin const downloadBackup = async (req, res) => { try { const { filename } = req.params; // Reject anything that isn't exactly the shape this app generates, before ever // touching the filesystem — same posture as the event-alias path-safety fix. if (!BACKUP_FILENAME_RE.test(filename)) { res.status(400); throw new Error('Invalid backup filename'); } const filePath = path.join(BACKUP_DIR, filename); if (!fs.existsSync(filePath)) { res.status(404); throw new Error('Backup not found'); } res.download(filePath, filename); } catch (e) { res.status(res.statusCode === 200 ? 400 : res.statusCode).json({ message: safeErrorMessage(e) }); } }; module.exports = { getBackups, triggerBackup, downloadBackup };