/** * Creates or repairs a SUPER_ADMIN account. * * pnpm --filter @sport/api run create-admin * ADMIN_EMAIL=me@example.com ADMIN_PASSWORD='…' pnpm ... run create-admin * * This is the production bootstrap path, and the reason the seed never creates * a privileged account with a known password. Safe to re-run: an existing * account has its password reset and its role re-granted, which doubles as the * "locked out of the admin" recovery procedure. */ import { PrismaClient } from '@prisma/client'; import { SYSTEM_ROLES } from '@sport/types'; import { generatePassword, hashPassword, verifyPassword } from './seed/accounts'; const prisma = new PrismaClient(); async function main(): Promise { const email = (process.env['ADMIN_EMAIL'] ?? 'admin@sport.local').trim().toLowerCase(); const provided = process.env['ADMIN_PASSWORD']; const password = provided ?? generatePassword(); if (provided && provided.length < 10) { throw new Error('ADMIN_PASSWORD must be at least 10 characters.'); } const passwordHash = await hashPassword(password); // Verify the hash round-trips before writing it. A malformed hash here would // create an account nobody can ever sign in to, and the failure would only // surface at the login screen. if (!(await verifyPassword(password, passwordHash))) { throw new Error('Password hash failed self-verification; refusing to write.'); } const role = await prisma.role.findUnique({ where: { key: SYSTEM_ROLES.SUPER_ADMIN } }); if (!role) { throw new Error('The super_admin role is missing. Run `pnpm db:seed` first.'); } const user = await prisma.user.upsert({ where: { email }, update: { passwordHash, status: 'ACTIVE', type: 'SUPER_ADMIN', deletedAt: null }, create: { email, passwordHash, type: 'SUPER_ADMIN', status: 'ACTIVE', firstName: 'Super', lastName: 'Admin', emailVerifiedAt: new Date(), }, select: { id: true }, }); await prisma.userRole.upsert({ where: { userId_roleId: { userId: user.id, roleId: role.id } }, update: {}, create: { userId: user.id, roleId: role.id }, }); console.log('\nSuper admin ready.\n'); console.log(` Email: ${email}`); if (provided) { console.log(' Password: (from ADMIN_PASSWORD)'); } else { console.log(` Password: ${password}`); console.log('\n Generated password — shown once. Store it now.'); } console.log(''); } main() .catch((error: unknown) => { console.error(error instanceof Error ? error.message : error); process.exitCode = 1; }) .finally(() => { void prisma.$disconnect(); });