import { Form, useActionData, useNavigation } from "react-router"; import { requireUser } from "@/session.server"; import prisma from "@/lib/prisma"; import bcrypt from "bcryptjs"; import { log } from "@/lib/logger"; import { Button } from "@/components/ui/button"; import { KeyRound, CheckCircle2 } from "lucide-react"; export const handle = { breadcrumbs: () => [{ label: "Passwort ändern" }], }; export async function loader({ request }: { request: Request }) { await requireUser(request); return null; } export async function action({ request }: { request: Request }) { const user = await requireUser(request); const form = await request.formData(); const current = form.get("current") as string; const next = form.get("next") as string; const confirm = form.get("confirm") as string; if (!current || !next || !confirm) { return { error: "Alle Felder sind erforderlich." }; } if (next.length < 8) { return { error: "Das neue Passwort muss mindestens 8 Zeichen lang sein." }; } if (next !== confirm) { return { error: "Die neuen Passwörter stimmen nicht überein." }; } const dbUser = await prisma.user.findUnique({ where: { id: user.id } }); if (!dbUser) return { error: "Benutzer nicht gefunden." }; const valid = await bcrypt.compare(current, dbUser.passwordHash); if (!valid) { return { error: "Das aktuelle Passwort ist falsch." }; } const passwordHash = await bcrypt.hash(next, 12); await prisma.user.update({ where: { id: user.id }, data: { passwordHash } }); await log({ userId: user.id, action: "CHANGE_PASSWORD", entity: "User", entityId: user.id, request }); return { success: true }; } export default function ChangePasswordPage() { const result = useActionData(); const navigation = useNavigation(); const submitting = navigation.state === "submitting"; return (

Passwort ändern

Geben Sie Ihr aktuelles und ein neues Passwort ein.

{result?.success ? (

Passwort erfolgreich geändert.

) : (
{result?.error && (
{result.error}
)}

Mindestens 8 Zeichen.

)}
); }