Add full /data backup export/import for server migration

- New admin endpoints: GET /api/admin-backup/export streams the entire
  data directory as tar.gz (after flushing queued writes); POST
  /api/admin-backup/import validates the archive, snapshots current
  data, replaces the folder, and reloads all in-memory state.
- Admin UI: "Full Data Backup" section with download and restore-from-
  file controls in the Analytics panel.
- Fix admin TOTP secret path to honor SITEFORGE_DATA_DIR (moved base
  path resolution to server/paths.js to avoid a circular import), so
  2FA for admin and study users survives backup/restore.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
nmemmert
2026-07-07 12:08:23 -04:00
parent 17c9cbbc8b
commit f4fd177421
9 changed files with 371 additions and 17 deletions
+15
View File
@@ -0,0 +1,15 @@
import path from 'node:path'
import { fileURLToPath } from 'node:url'
// Base directory resolution lives in its own module (no app imports) so that
// both config.js and auth.js can use DATA_DIR without a circular dependency.
const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)
// server/paths.js is inside server/, so the project root is one level up
export const ROOT_DIR = path.resolve(__dirname, '..')
const DEFAULT_DATA_DIR = path.join(ROOT_DIR, 'data')
const configuredDataDir = typeof process.env.SITEFORGE_DATA_DIR === 'string' ? process.env.SITEFORGE_DATA_DIR.trim() : ''
export const DATA_DIR = configuredDataDir
? (path.isAbsolute(configuredDataDir) ? configuredDataDir : path.resolve(ROOT_DIR, configuredDataDir))
: DEFAULT_DATA_DIR