"use server"; import { hash } from "bcryptjs"; import { z } from "zod"; import { signIn } from "@/auth"; import { prisma } from "@/lib/prisma"; // ===================================================================== // /invite/[token] · Server Action // --------------------------------------------------------------------- // acceptInviteAction: // 1. Token erneut gegen DB prüfen (kein Trust auf Client-State) // 2. Passwort hashen + User-Daten setzen (DSGVO-Timestamps) // 3. Token löschen (kein Replay möglich) // 4. Direkt einloggen + Redirect auf /dashboard // ===================================================================== const inviteSchema = z .object({ token: z.string().min(1), password: z.string().min(8, "Mindestens 8 Zeichen.").max(72, "Maximal 72 Zeichen."), confirmPassword: z.string().min(1, "Passwort-Bestätigung fehlt."), acceptPrivacyPolicy: z.literal("on", { error: "Bitte die Datenschutzerklärung akzeptieren.", }), directoryOptIn: z.enum(["on", "off"]).optional(), }) .refine((d) => d.password === d.confirmPassword, { message: "Passwörter stimmen nicht überein.", path: ["confirmPassword"], }); const PRIVACY_POLICY_VERSION = "2026-05-01"; export type InviteState = { // Bumped per call so the client can key uncontrolled inputs and force a // remount after a failed submit (React's