Datenbank bereinigt / Gitea-Integration gefixt

Dieser Commit ist enthalten in:
hendrik_gebhardt@gmx.de
2026-01-04 00:24:11 +00:00
committet von Server Deploy
Ursprung 395598c2b0
Commit c21be47428
37 geänderte Dateien mit 30993 neuen und 809 gelöschten Zeilen

Datei anzeigen

@ -7,6 +7,7 @@
const fs = require('fs');
const path = require('path');
const logger = require('./logger');
const { encryptFile, decryptFile, secureDelete } = require('./encryption');
const DATA_DIR = process.env.DATA_DIR || path.join(__dirname, '..', 'data');
const BACKUP_DIR = process.env.BACKUP_DIR || path.join(__dirname, '..', 'backups');
@ -17,8 +18,9 @@ if (!fs.existsSync(BACKUP_DIR)) {
fs.mkdirSync(BACKUP_DIR, { recursive: true });
}
/**
* Backup erstellen
* Backup erstellen (mit einfacher Verschlüsselung)
*/
function createBackup() {
try {
@ -29,12 +31,27 @@ function createBackup() {
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
const backupName = `backup_${timestamp}.db`;
const encryptedName = `backup_${timestamp}.db.enc`;
const backupPath = path.join(BACKUP_DIR, backupName);
const encryptedPath = path.join(BACKUP_DIR, encryptedName);
// Datenbank kopieren
// 1. Normales Backup erstellen (für Kompatibilität)
fs.copyFileSync(DB_FILE, backupPath);
// WAL-Datei auch sichern falls vorhanden
// 2. Verschlüsseltes Backup erstellen (zusätzlich)
if (process.env.ENCRYPTION_KEY) {
try {
if (encryptFile(DB_FILE, encryptedPath)) {
logger.info(`Verschlüsseltes Backup erstellt: ${encryptedName}`);
} else {
logger.warn('Verschlüsselung fehlgeschlagen, nur normales Backup erstellt');
}
} catch (encError) {
logger.warn('Verschlüsselung fehlgeschlagen, nur normales Backup erstellt');
}
}
// 3. WAL-Datei sichern falls vorhanden
const walFile = DB_FILE + '-wal';
if (fs.existsSync(walFile)) {
fs.copyFileSync(walFile, backupPath + '-wal');
@ -53,12 +70,12 @@ function createBackup() {
}
/**
* Alte Backups löschen
* Alte Backups löschen (verschlüsselte)
*/
function cleanupOldBackups(keepCount = 30) {
try {
const files = fs.readdirSync(BACKUP_DIR)
.filter(f => f.startsWith('backup_') && f.endsWith('.db'))
.filter(f => f.startsWith('backup_') && f.endsWith('.db.enc'))
.sort()
.reverse();
@ -66,15 +83,15 @@ function cleanupOldBackups(keepCount = 30) {
toDelete.forEach(file => {
const filePath = path.join(BACKUP_DIR, file);
fs.unlinkSync(filePath);
secureDelete(filePath);
// WAL-Datei auch löschen falls vorhanden
// Verschlüsselte WAL-Datei auch löschen falls vorhanden
const walPath = filePath + '-wal';
if (fs.existsSync(walPath)) {
fs.unlinkSync(walPath);
secureDelete(walPath);
}
logger.info(`Altes Backup gelöscht: ${file}`);
logger.info(`Altes Backup sicher gelöscht: ${file}`);
});
} catch (error) {
logger.error('Fehler beim Aufräumen alter Backups:', { error: error.message });
@ -82,32 +99,50 @@ function cleanupOldBackups(keepCount = 30) {
}
/**
* Backup wiederherstellen
* Backup wiederherstellen (entschlüsselt)
*/
function restoreBackup(backupName) {
try {
const backupPath = path.join(BACKUP_DIR, backupName);
const encryptedBackupPath = path.join(BACKUP_DIR, backupName);
if (!fs.existsSync(backupPath)) {
if (!fs.existsSync(encryptedBackupPath)) {
throw new Error(`Backup nicht gefunden: ${backupName}`);
}
// Aktuelles DB sichern bevor überschrieben wird
// Aktuelles DB verschlüsselt sichern bevor überschrieben wird
if (fs.existsSync(DB_FILE)) {
const safetyBackup = DB_FILE + '.before-restore';
fs.copyFileSync(DB_FILE, safetyBackup);
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
const safetyBackupPath = DB_FILE + `.before-restore-${timestamp}.enc`;
if (!encryptFile(DB_FILE, safetyBackupPath)) {
logger.warn('Sicherheitsbackup vor Wiederherstellung fehlgeschlagen');
}
}
// Backup wiederherstellen
fs.copyFileSync(backupPath, DB_FILE);
// Temporäre entschlüsselte Datei
const tempRestorePath = path.join(BACKUP_DIR, `temp_restore_${Date.now()}.db`);
// Backup entschlüsseln
if (!decryptFile(encryptedBackupPath, tempRestorePath)) {
throw new Error('Backup-Entschlüsselung fehlgeschlagen');
}
// Entschlüsselte DB kopieren
fs.copyFileSync(tempRestorePath, DB_FILE);
// WAL-Datei auch wiederherstellen falls vorhanden
const walBackup = backupPath + '-wal';
if (fs.existsSync(walBackup)) {
fs.copyFileSync(walBackup, DB_FILE + '-wal');
const encryptedWalBackup = encryptedBackupPath + '-wal';
if (fs.existsSync(encryptedWalBackup)) {
const tempWalPath = tempRestorePath + '-wal';
if (decryptFile(encryptedWalBackup, tempWalPath)) {
fs.copyFileSync(tempWalPath, DB_FILE + '-wal');
secureDelete(tempWalPath);
}
}
logger.info(`Backup wiederhergestellt: ${backupName}`);
// Temporäre entschlüsselte Dateien sicher löschen
secureDelete(tempRestorePath);
logger.info(`Verschlüsseltes Backup wiederhergestellt: ${backupName}`);
return true;
} catch (error) {
logger.error('Restore-Fehler:', { error: error.message });
@ -116,12 +151,12 @@ function restoreBackup(backupName) {
}
/**
* Liste aller Backups
* Liste aller verschlüsselten Backups
*/
function listBackups() {
try {
const files = fs.readdirSync(BACKUP_DIR)
.filter(f => f.startsWith('backup_') && f.endsWith('.db'))
.filter(f => f.startsWith('backup_') && f.endsWith('.db.enc'))
.map(f => {
const filePath = path.join(BACKUP_DIR, f);
const stats = fs.statSync(filePath);