Backup-Seite zeigt zwei neue Log-Panels: links Backup-Erstellung, rechts Backup-Wiederherstellung. Jeder Eintrag mit ✓/✗-Status, Summary, Timestamp + User. Klick öffnet Modal mit vollständigem Verlauf – alle console.log/error/warn/info-Zeilen werden während der Operation in einen Puffer mitgefangen und im fullLog-Feld persistiert. Auto-Refresh alle 5s. Persistenz: neue Tabelle BackupLog mit Migration 20260519100000_backup_log (CREATE TABLE IF NOT EXISTS für Re-Deploys auf DBs mit Vorab-db-push). fullLog auf 1 MB gecappt. Endpoints (settings:update): - GET /api/settings/backup-logs?operation=CREATE|RESTORE&limit=50 - GET /api/settings/backup-logs/:id EBUSY-Fix: Der neue Log-Verlauf hat sofort einen alten Bug sichtbar gemacht. backup.service.restoreBackup rief deleteDirectory(UPLOADS_DIR) auf, dessen finales rmdirSync auf /app/uploads ein EBUSY warf – das Verzeichnis ist im Container ein Bind-Mount und lässt sich nicht aushängen. Fix: neuer Helper emptyDirectory() löscht nur die Inhalte, das Verzeichnis bleibt stehen. Live-verifiziert: 4867 Datensätze + 1 Datei in 13.2s wiederhergestellt; Log-Modal zeigt den vollständigen Verlauf. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
133 lines
3.2 KiB
TypeScript
133 lines
3.2 KiB
TypeScript
import { Router } from 'express';
|
|
import multer from 'multer';
|
|
import * as appSettingController from '../controllers/appSetting.controller.js';
|
|
import * as backupController from '../controllers/backup.controller.js';
|
|
import * as rateLimitAdminController from '../controllers/rateLimitAdmin.controller.js';
|
|
import { authenticate, requirePermission } from '../middleware/auth.js';
|
|
|
|
// Multer für Backup-Upload (in Memory speichern)
|
|
const backupUpload = multer({
|
|
storage: multer.memoryStorage(),
|
|
limits: { fileSize: 500 * 1024 * 1024 }, // 500MB max
|
|
fileFilter: (req, file, cb) => {
|
|
if (file.mimetype === 'application/zip' || file.originalname.endsWith('.zip')) {
|
|
cb(null, true);
|
|
} else {
|
|
cb(new Error('Nur ZIP-Dateien sind erlaubt'));
|
|
}
|
|
},
|
|
});
|
|
|
|
const router = Router();
|
|
|
|
// Öffentliche Einstellungen (für alle authentifizierten Benutzer, inkl. Kunden)
|
|
router.get('/public', authenticate, appSettingController.getPublicSettings);
|
|
|
|
// Alle Einstellungen (nur Admin)
|
|
router.get('/', authenticate, requirePermission('settings:read'), appSettingController.getAllSettings);
|
|
|
|
// Einzelne Einstellung aktualisieren (nur Admin)
|
|
router.put(
|
|
'/:key',
|
|
authenticate,
|
|
requirePermission('settings:update'),
|
|
appSettingController.updateSetting
|
|
);
|
|
|
|
// Mehrere Einstellungen aktualisieren (nur Admin)
|
|
router.put(
|
|
'/',
|
|
authenticate,
|
|
requirePermission('settings:update'),
|
|
appSettingController.updateSettings
|
|
);
|
|
|
|
// ==================== BACKUP & RESTORE ====================
|
|
|
|
// Liste aller Backups
|
|
router.get(
|
|
'/backups',
|
|
authenticate,
|
|
requirePermission('settings:update'),
|
|
backupController.listBackups
|
|
);
|
|
|
|
// Neues Backup erstellen
|
|
router.post(
|
|
'/backup',
|
|
authenticate,
|
|
requirePermission('settings:update'),
|
|
backupController.createBackup
|
|
);
|
|
|
|
// Backup wiederherstellen
|
|
router.post(
|
|
'/backup/:name/restore',
|
|
authenticate,
|
|
requirePermission('settings:update'),
|
|
backupController.restoreBackup
|
|
);
|
|
|
|
// Backup löschen
|
|
router.delete(
|
|
'/backup/:name',
|
|
authenticate,
|
|
requirePermission('settings:update'),
|
|
backupController.deleteBackup
|
|
);
|
|
|
|
// Backup als ZIP herunterladen
|
|
router.get(
|
|
'/backup/:name/download',
|
|
authenticate,
|
|
requirePermission('settings:update'),
|
|
backupController.downloadBackup
|
|
);
|
|
|
|
// Backup-ZIP hochladen
|
|
router.post(
|
|
'/backup/upload',
|
|
authenticate,
|
|
requirePermission('settings:update'),
|
|
backupUpload.single('backup'),
|
|
backupController.uploadBackup
|
|
);
|
|
|
|
// Werkseinstellungen (alles löschen)
|
|
router.post(
|
|
'/factory-reset',
|
|
authenticate,
|
|
requirePermission('settings:update'),
|
|
backupController.factoryReset
|
|
);
|
|
|
|
// Backup-Operations-Log: Liste (ohne fullLog) + Detail
|
|
router.get(
|
|
'/backup-logs',
|
|
authenticate,
|
|
requirePermission('settings:update'),
|
|
backupController.listBackupLogs
|
|
);
|
|
router.get(
|
|
'/backup-logs/:id',
|
|
authenticate,
|
|
requirePermission('settings:update'),
|
|
backupController.getBackupLogDetail
|
|
);
|
|
|
|
// Rate-Limit-Verwaltung (Admin)
|
|
router.get(
|
|
'/rate-limits/active',
|
|
authenticate,
|
|
requirePermission('settings:read'),
|
|
rateLimitAdminController.getActiveRateLimits,
|
|
);
|
|
router.post(
|
|
'/rate-limits/reset',
|
|
authenticate,
|
|
requirePermission('settings:update'),
|
|
rateLimitAdminController.resetRateLimit,
|
|
);
|
|
|
|
export default router;
|