64 lines
1.9 KiB
TypeScript
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 }
|
|
);
|
|
}
|
|
}
|