homelab-dashboard/app/api/setup/route.ts
Bilal Teke 69c2057252 v4
2026-04-20 14:34:07 +02:00

64 lines
1.9 KiB
TypeScript

import { NextResponse } from 'next/server';
import { hash } from 'bcryptjs';
import { z } from 'zod';
import { createInitialAdmin, hasAnyUser } from '@/src/lib/db/user';
const setupSchema = z.object({
username: z
.string()
.trim()
.min(3, 'Der Benutzername muss mindestens 3 Zeichen lang sein.')
.max(50, 'Der Benutzername darf höchstens 50 Zeichen lang sein.')
.regex(/^[a-zA-Z0-9._-]+$/, 'Der Benutzername enthält ungültige Zeichen.'),
password: z
.string()
.min(8, 'Das Passwort muss mindestens 8 Zeichen lang sein.')
.max(128, 'Das Passwort darf höchstens 128 Zeichen lang sein.'),
});
export async function POST(request: Request) {
try {
if (await hasAnyUser()) {
return NextResponse.json({ message: 'Ein Administrator existiert bereits.' }, { status: 403 });
}
let body: unknown;
try {
body = await request.json();
} catch (error) {
return NextResponse.json(
{ message: 'Der Request-Body muss gültiges JSON sein.' },
{ status: 400 }
);
}
const result = setupSchema.safeParse(body);
if (!result.success) {
return NextResponse.json(
{ message: result.error.issues[0]?.message || 'Ungültige Setup-Daten.' },
{ status: 400 }
);
}
const passwordHash = await hash(result.data.password, 10);
try {
await createInitialAdmin(result.data.username, passwordHash);
return NextResponse.json({ message: 'Administrator wurde erfolgreich angelegt.' }, { status: 201 });
} catch (error) {
if (error instanceof Error && error.message === 'INITIAL_ADMIN_ALREADY_EXISTS') {
return NextResponse.json({ message: 'Ein Administrator existiert bereits.' }, { status: 403 });
}
throw error;
}
} catch (error) {
console.error('POST /api/setup failed:', error);
return NextResponse.json(
{ message: 'Setup konnte nicht abgeschlossen werden.' },
{ status: 500 }
);
}
}