Fix
This commit is contained in:
@@ -51,7 +51,7 @@ export async function runAutoExport() {
|
|||||||
console.log('[autoExport] Démarrage de l\'export automatique…');
|
console.log('[autoExport] Démarrage de l\'export automatique…');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await db.backup(tmpDb);
|
db.exec(`VACUUM INTO '${tmpDb.replace(/'/g, "''")}'`);
|
||||||
const dbData = fs.readFileSync(tmpDb);
|
const dbData = fs.readFileSync(tmpDb);
|
||||||
|
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import path from 'node:path';
|
|||||||
import os from 'node:os';
|
import os from 'node:os';
|
||||||
import { fileURLToPath } from 'node:url';
|
import { fileURLToPath } from 'node:url';
|
||||||
import db from '../db/index.js';
|
import db from '../db/index.js';
|
||||||
|
import Database from 'better-sqlite3';
|
||||||
import { HttpError } from '../middleware/errorHandler.js';
|
import { HttpError } from '../middleware/errorHandler.js';
|
||||||
import { checkStatutsRetard } from '../jobs/autoStatut.js';
|
import { checkStatutsRetard } from '../jobs/autoStatut.js';
|
||||||
import { runAutoExport } from '../jobs/autoExport.js';
|
import { runAutoExport } from '../jobs/autoExport.js';
|
||||||
@@ -453,10 +454,10 @@ function purgeOldExports() {
|
|||||||
* GET /api/admin/export-full
|
* GET /api/admin/export-full
|
||||||
* Génère un export ZIP, le sauvegarde sur disque, et le retourne au navigateur.
|
* Génère un export ZIP, le sauvegarde sur disque, et le retourne au navigateur.
|
||||||
*/
|
*/
|
||||||
router.get('/export-full', async (req, res, next) => {
|
router.get('/export-full', (req, res, next) => {
|
||||||
const tmpDb = path.join(os.tmpdir(), `cl-backup-${Date.now()}.db`);
|
const tmpDb = path.join(os.tmpdir(), `cl-backup-${Date.now()}.db`);
|
||||||
try {
|
try {
|
||||||
await db.backup(tmpDb);
|
db.exec(`VACUUM INTO '${tmpDb.replace(/'/g, "''")}'`);
|
||||||
const dbData = fs.readFileSync(tmpDb);
|
const dbData = fs.readFileSync(tmpDb);
|
||||||
|
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
@@ -617,7 +618,7 @@ router.post('/exports/:filename/restore', async (req, res, next) => {
|
|||||||
if (!dbEntry) throw new HttpError(400, 'crowdlending.db introuvable dans l\'archive');
|
if (!dbEntry) throw new HttpError(400, 'crowdlending.db introuvable dans l\'archive');
|
||||||
|
|
||||||
// 1. Sauvegarde de sécurité de l'état courant
|
// 1. Sauvegarde de sécurité de l'état courant
|
||||||
await db.backup(tmpDb);
|
db.exec(`VACUUM INTO '${tmpDb.replace(/'/g, "''")}'`);
|
||||||
const backupEntries = [];
|
const backupEntries = [];
|
||||||
backupEntries.push({
|
backupEntries.push({
|
||||||
name: 'manifest.json',
|
name: 'manifest.json',
|
||||||
@@ -656,7 +657,25 @@ router.post('/exports/:filename/restore', async (req, res, next) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Écriture du pending-restore (appliqué par db/index.js au prochain démarrage)
|
// 3. Validation + écriture du pending-restore
|
||||||
|
{
|
||||||
|
const tmpValidate = path.join(os.tmpdir(), `cl-validate-${Date.now()}.db`);
|
||||||
|
let testDb;
|
||||||
|
try {
|
||||||
|
fs.writeFileSync(tmpValidate, dbEntry.data);
|
||||||
|
testDb = new Database(tmpValidate, { readonly: true });
|
||||||
|
const check = testDb.pragma('integrity_check');
|
||||||
|
if (!check || check[0]?.integrity_check !== 'ok') {
|
||||||
|
throw new HttpError(500, `Base de données corrompue dans l'archive — integrity_check: ${JSON.stringify(check?.[0])}`);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
if (e instanceof HttpError) throw e;
|
||||||
|
throw new HttpError(500, `Base de données invalide dans l'archive : ${e.message}`);
|
||||||
|
} finally {
|
||||||
|
if (testDb) try { testDb.close(); } catch {}
|
||||||
|
if (fs.existsSync(tmpValidate)) try { fs.unlinkSync(tmpValidate); } catch {}
|
||||||
|
}
|
||||||
|
}
|
||||||
fs.writeFileSync(dbPath + '.pending-restore', dbEntry.data);
|
fs.writeFileSync(dbPath + '.pending-restore', dbEntry.data);
|
||||||
|
|
||||||
// 4. Réponse puis redémarrage
|
// 4. Réponse puis redémarrage
|
||||||
|
|||||||
Reference in New Issue
Block a user