Initial commit — Mek-Tech AI Consultancy Framework v2.0
This commit is contained in:
@@ -0,0 +1,126 @@
|
||||
const express = require('express');
|
||||
const router = express.Router();
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const multer = require('multer');
|
||||
const { getDb, logAudit } = require('../db');
|
||||
const {
|
||||
collectStats,
|
||||
formatBytes,
|
||||
createBackup,
|
||||
listBackups,
|
||||
getBackupPath,
|
||||
deleteBackup,
|
||||
restoreBackup,
|
||||
getPaths
|
||||
} = require('../lib/backup');
|
||||
|
||||
function requireAdmin(req, res, next) {
|
||||
const db = getDb();
|
||||
const user = db.prepare('SELECT * FROM users WHERE id = ?').get(req.session.userId);
|
||||
if (!user || user.role !== 'admin') return res.status(403).render('404', { path: req.path });
|
||||
next();
|
||||
}
|
||||
|
||||
const uploadDir = path.join(getPaths().dataDir, 'backups', 'uploads-tmp');
|
||||
if (!fs.existsSync(uploadDir)) fs.mkdirSync(uploadDir, { recursive: true });
|
||||
|
||||
const upload = multer({
|
||||
dest: uploadDir,
|
||||
limits: { fileSize: 500 * 1024 * 1024 },
|
||||
fileFilter: (req, file, cb) => {
|
||||
if (file.originalname.endsWith('.tar.gz') || file.originalname.endsWith('.tgz') || file.mimetype === 'application/gzip') {
|
||||
cb(null, true);
|
||||
} else {
|
||||
cb(new Error('Alleen .tar.gz backupbestanden'));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
router.get('/', requireAdmin, (req, res) => {
|
||||
const stats = collectStats();
|
||||
const backups = listBackups();
|
||||
const disk = getPaths();
|
||||
let diskFree = null;
|
||||
try {
|
||||
const { execSync } = require('child_process');
|
||||
const out = execSync(`df -B1 "${disk.dataDir}" 2>/dev/null | tail -1`, { encoding: 'utf8' });
|
||||
const parts = out.trim().split(/\s+/);
|
||||
if (parts.length >= 4) diskFree = formatBytes(parseInt(parts[3], 10));
|
||||
} catch (e) { /* ignore */ }
|
||||
|
||||
res.render('backup', {
|
||||
stats,
|
||||
backups,
|
||||
diskFree,
|
||||
formatBytes,
|
||||
restored: req.query.restored === '1',
|
||||
created: req.query.created === '1',
|
||||
deleted: req.query.deleted === '1',
|
||||
error: req.query.error || null,
|
||||
user: { username: req.session.username }
|
||||
});
|
||||
});
|
||||
|
||||
router.post('/create', requireAdmin, (req, res) => {
|
||||
try {
|
||||
const backup = createBackup();
|
||||
logAudit(req.session.userId, req.session.username, 'backup_create', 'system', 0, backup.filename);
|
||||
if (req.query.download === '1') {
|
||||
return res.download(backup.path, backup.filename);
|
||||
}
|
||||
res.redirect('/backup?created=1');
|
||||
} catch (e) {
|
||||
console.error('Backup create error:', e);
|
||||
res.redirect('/backup?error=' + encodeURIComponent('Backup mislukt: ' + e.message));
|
||||
}
|
||||
});
|
||||
|
||||
router.get('/download/:filename', requireAdmin, (req, res) => {
|
||||
const p = getBackupPath(req.params.filename);
|
||||
if (!p) return res.redirect('/backup?error=' + encodeURIComponent('Backup niet gevonden'));
|
||||
logAudit(req.session.userId, req.session.username, 'backup_download', 'system', 0, req.params.filename);
|
||||
res.download(p, req.params.filename);
|
||||
});
|
||||
|
||||
router.post('/delete/:filename', requireAdmin, (req, res) => {
|
||||
try {
|
||||
if (!deleteBackup(req.params.filename)) {
|
||||
return res.redirect('/backup?error=' + encodeURIComponent('Backup niet gevonden'));
|
||||
}
|
||||
logAudit(req.session.userId, req.session.username, 'backup_delete', 'system', 0, req.params.filename);
|
||||
res.redirect('/backup?deleted=1');
|
||||
} catch (e) {
|
||||
res.redirect('/backup?error=' + encodeURIComponent(e.message));
|
||||
}
|
||||
});
|
||||
|
||||
router.post('/restore', requireAdmin, upload.single('backup_file'), (req, res) => {
|
||||
if (!req.file) {
|
||||
return res.redirect('/backup?error=' + encodeURIComponent('Geen bestand geüpload'));
|
||||
}
|
||||
try {
|
||||
const result = restoreBackup(req.file.path);
|
||||
fs.unlinkSync(req.file.path);
|
||||
logAudit(req.session.userId, req.session.username, 'backup_restore', 'system', 0, JSON.stringify(result));
|
||||
res.redirect('/backup?restored=1');
|
||||
} catch (e) {
|
||||
console.error('Restore error:', e);
|
||||
try { fs.unlinkSync(req.file.path); } catch (err) { /* ignore */ }
|
||||
res.redirect('/backup?error=' + encodeURIComponent('Herstel mislukt: ' + e.message));
|
||||
}
|
||||
});
|
||||
|
||||
router.post('/restore/:filename', requireAdmin, (req, res) => {
|
||||
const p = getBackupPath(req.params.filename);
|
||||
if (!p) return res.redirect('/backup?error=' + encodeURIComponent('Backup niet gevonden'));
|
||||
try {
|
||||
const result = restoreBackup(p);
|
||||
logAudit(req.session.userId, req.session.username, 'backup_restore', 'system', 0, req.params.filename);
|
||||
res.redirect('/backup?restored=1');
|
||||
} catch (e) {
|
||||
res.redirect('/backup?error=' + encodeURIComponent('Herstel mislukt: ' + e.message));
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
Reference in New Issue
Block a user