Files
MIKROTIK-RMM/backend/src/routes/backups.ts
T
2026-04-13 18:15:41 -07:00

93 lines
3.2 KiB
TypeScript

import { Router, Request, Response } from 'express';
import * as fs from 'fs';
import * as path from 'path';
import { query, queryOne } from '../config/database';
import { requireAuth, requireWrite } from '../middleware/auth';
import { BackupService } from '../services/BackupService';
const router = Router();
router.use(requireAuth);
const backupService = new BackupService();
// GET /api/backups
router.get('/', async (req: Request, res: Response) => {
const { deviceId } = req.query;
let sql = `
SELECT b.*, d.name as device_name
FROM backups b JOIN devices d ON d.id = b.device_id
WHERE 1=1
`;
const params: unknown[] = [];
if (deviceId) {
sql += ` AND b.device_id = $1`;
params.push(deviceId);
}
sql += ' ORDER BY b.created_at DESC';
const backups = await query(sql, params);
res.json(backups);
});
// POST /api/backups
router.post('/', requireWrite, async (req: Request, res: Response) => {
const { deviceId, notes } = req.body;
if (!deviceId) return res.status(400).json({ error: 'deviceId is required' });
const device = await queryOne<any>(
`SELECT id, name, ip_address, ssh_port, ssh_username, ssh_password_encrypted,
api_username, api_password_encrypted
FROM devices WHERE id = $1`,
[deviceId]
);
if (!device) return res.status(404).json({ error: 'Device not found' });
try {
const backupId = await backupService.createBackup(device, notes);
const backup = await queryOne(`SELECT * FROM backups WHERE id = $1`, [backupId]);
return res.status(201).json(backup);
} catch (err) {
return res.status(500).json({ error: `Backup failed: ${(err as Error).message}` });
}
});
// GET /api/backups/:id/download
router.get('/:id/download', async (req: Request, res: Response) => {
const backup = await queryOne<{ file_path: string; filename: string }>(
`SELECT file_path, filename FROM backups WHERE id = $1`,
[req.params.id]
);
if (!backup) return res.status(404).json({ error: 'Backup not found' });
if (!fs.existsSync(backup.file_path)) {
return res.status(404).json({ error: 'Backup file not found on disk' });
}
res.setHeader('Content-Disposition', `attachment; filename="${backup.filename}"`);
res.setHeader('Content-Type', 'text/plain');
return res.sendFile(path.resolve(backup.file_path));
});
// POST /api/backups/:id/restore
router.post('/:id/restore', requireWrite, async (req: Request, res: Response) => {
const backup = await queryOne(`SELECT id FROM backups WHERE id = $1`, [req.params.id]);
if (!backup) return res.status(404).json({ error: 'Backup not found' });
try {
await backupService.restoreBackup(parseInt(req.params.id));
return res.json({ message: 'Restore initiated successfully' });
} catch (err) {
return res.status(500).json({ error: `Restore failed: ${(err as Error).message}` });
}
});
// DELETE /api/backups/:id
router.delete('/:id', requireWrite, async (req: Request, res: Response) => {
const backup = await queryOne(`SELECT id FROM backups WHERE id = $1`, [req.params.id]);
if (!backup) return res.status(404).json({ error: 'Backup not found' });
await backupService.deleteBackup(parseInt(req.params.id));
return res.json({ message: 'Backup deleted' });
});
export default router;