"use server"; import { prisma } from "@capakraken/db"; import { SystemRole } from "@capakraken/db"; import { PASSWORD_MAX_LENGTH, PASSWORD_MIN_LENGTH, PASSWORD_POLICY_MESSAGE, } from "@capakraken/shared"; export type SetupResult = | { success: true } | { error: "alreadySetup" | "emailTaken" | "validation"; message?: string }; export async function createFirstAdmin(formData: { name: string; email: string; password: string; }): Promise { // Validate if (!formData.name.trim()) return { error: "validation", message: "Name is required." }; if (!formData.email.includes("@")) return { error: "validation", message: "Valid email required." }; if ( formData.password.length < PASSWORD_MIN_LENGTH || formData.password.length > PASSWORD_MAX_LENGTH ) { return { error: "validation", message: PASSWORD_POLICY_MESSAGE }; } // TOCTOU guard — check again inside the action const count = await prisma.user.count(); if (count > 0) return { error: "alreadySetup" }; const { hash } = await import("@node-rs/argon2"); const passwordHash = await hash(formData.password); try { await prisma.user.create({ data: { email: formData.email.toLowerCase().trim(), name: formData.name.trim(), passwordHash, systemRole: SystemRole.ADMIN, isActive: true, }, }); return { success: true }; } catch (err: unknown) { const message = err instanceof Error ? err.message : String(err); if (message.includes("Unique constraint") || message.includes("unique")) { return { error: "emailTaken" }; } throw err; } }