import { randomBytes } from 'node:crypto'; import { ProductTarget } from '@prisma/client'; import { prisma } from './db.js'; import { env } from './env.js'; import { hashPassword } from './auth/password.js'; // Startpunkte fuer die Produkterkennung beim Import. Jederzeit im Admin-Bereich // anpassbar, sobald die echten Produktnamen bekannt sind. const DEFAULT_MAPPINGS = [ { matchPattern: 'cc-paket', target: ProductTarget.CC_PACKAGE, priority: 10 }, { matchPattern: 'cc paket', target: ProductTarget.CC_PACKAGE, priority: 11 }, { matchPattern: 'custom character', target: ProductTarget.CC_PACKAGE, priority: 12 }, { matchPattern: 'redesign', target: ProductTarget.REDESIGN_PACKAGE, priority: 20 }, ]; export interface BootstrapResult { createdAdmin: { username: string; password: string } | null; createdMappings: number; } /** * Legt beim allerersten Start einen Administrator an. Ohne gesetztes * Bootstrap-Passwort wird eines erzeugt und einmalig ins Log geschrieben. */ export async function bootstrap(log: { info: (msg: string) => void; warn: (msg: string) => void; }): Promise { const result: BootstrapResult = { createdAdmin: null, createdMappings: 0 }; const userCount = await prisma.user.count(); if (userCount === 0) { const password = env.BOOTSTRAP_ADMIN_PASSWORD ?? randomBytes(12).toString('base64url'); await prisma.user.create({ data: { username: env.BOOTSTRAP_ADMIN_USER, passwordHash: await hashPassword(password), role: 'ADMIN', mustChangePassword: true, }, }); result.createdAdmin = { username: env.BOOTSTRAP_ADMIN_USER, password }; log.warn('─'.repeat(60)); log.warn(`Administrator angelegt: ${env.BOOTSTRAP_ADMIN_USER}`); if (!env.BOOTSTRAP_ADMIN_PASSWORD) { log.warn(`Einmal-Passwort: ${password}`); } log.warn('Das Passwort muss bei der ersten Anmeldung geaendert werden.'); log.warn('─'.repeat(60)); } const mappingCount = await prisma.productMapping.count(); if (mappingCount === 0) { const created = await prisma.productMapping.createMany({ data: DEFAULT_MAPPINGS }); result.createdMappings = created.count; log.info(`${created.count} Produkt-Mappings als Startwerte angelegt`); } return result; }