import { Form, useActionData, useNavigation, redirect, Link } from "react-router"; import { requireAdmin } from "@/session.server"; import { log } from "@/lib/logger.server"; import prisma from "@/lib/prisma.server"; import bcrypt from "bcryptjs"; import { AlertCircle, ArrowLeft } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; export async function loader({ request }: { request: Request }) { await requireAdmin(request); return null; } export async function action({ request }: { request: Request }) { const admin = await requireAdmin(request); const formData = await request.formData(); const name = (formData.get("name") as string).trim(); const username = (formData.get("username") as string).trim().toLowerCase(); const email = (formData.get("email") as string).trim().toLowerCase(); const password = formData.get("password") as string; const role = formData.get("role") as "USER" | "ADMIN"; if (!name || !username || !email || !password) { return { error: "Alle Felder sind Pflichtfelder." }; } if (password.length < 8) { return { error: "Das Passwort muss mindestens 8 Zeichen lang sein." }; } const existing = await prisma.user.findFirst({ where: { OR: [{ email }, { username }] }, }); if (existing) { return { error: "E-Mail oder Benutzername bereits vergeben." }; } const passwordHash = await bcrypt.hash(password, 12); const user = await prisma.user.create({ data: { name, username, email, passwordHash, role: role === "ADMIN" ? "ADMIN" : "USER" }, }); await log({ userId: admin.id, action: "CREATE_USER", entity: "User", entityId: user.id, metadata: { name, username, email, role }, request, }); return redirect("/admin/users"); } export default function AdminUsersNewPage() { const actionData = useActionData(); const navigation = useNavigation(); const loading = navigation.state === "submitting"; return (

Neuer Benutzer

Zugangsdaten und Rolle festlegen

{actionData?.error && (
{actionData.error}
)}

Mindestens 8 Zeichen

); }