feat(m14): backup & admin (zip via fflate, admin guard, tests, e2e)
- BackupService (admin-only: createBackup zips DB+uploads via fflate to backups/backup-<ts>.zip, listBackups newest-first, getBackupPath with path-traversal guard) - Admin backup APIs: GET/POST /api/admin/backups, GET /api/admin/backups/:filename - Admin backups screen (admin-only) + BackupCreateButton - Playwright globalSetup seeds a system_admin user for admin E2E - add fflate dependency - Unit tests (BackupService: zip content, list, admin guard, traversal) + e2e backup (create/list/download + non-admin 403)
This commit is contained in:
34
tests/e2e/globalSetup.ts
Normal file
34
tests/e2e/globalSetup.ts
Normal file
@ -0,0 +1,34 @@
|
||||
import bcrypt from 'bcrypt';
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import { SqliteDatabase } from '@/lib/db/sqlite';
|
||||
import { Migrator } from '@/lib/db/migrator';
|
||||
import { UserRepository } from '@/repositories/UserRepository';
|
||||
|
||||
const ADMIN_EMAIL = 'admin@example.com';
|
||||
const ADMIN_PASSWORD = 'admin123';
|
||||
|
||||
/**
|
||||
* E2E用の初期データをセットアップする。
|
||||
* - Migrationを確実に適用(開発サーバのmigrateと重複しても冪等)
|
||||
* - バックアップ/管理者機能のE2Eで使用する system_admin ユーザーを生成
|
||||
*/
|
||||
export default async function globalSetup(): Promise<void> {
|
||||
const dbPath = process.env.SQLITE_PATH ?? './data/app.db';
|
||||
fs.mkdirSync(path.dirname(dbPath), { recursive: true });
|
||||
|
||||
const db = new SqliteDatabase(dbPath);
|
||||
const migrationsDir = path.join(process.cwd(), 'lib', 'db', 'migrations');
|
||||
new Migrator(db, migrationsDir).migrate();
|
||||
|
||||
const userRepo = new UserRepository(db);
|
||||
if (!userRepo.findByEmail(ADMIN_EMAIL)) {
|
||||
userRepo.create({
|
||||
name: 'Admin',
|
||||
email: ADMIN_EMAIL,
|
||||
passwordHash: bcrypt.hashSync(ADMIN_PASSWORD, 10),
|
||||
role: 'system_admin',
|
||||
});
|
||||
}
|
||||
db.close();
|
||||
}
|
||||
Reference in New Issue
Block a user