"use server"; import { revalidatePath } from "next/cache"; import { redirect } from "next/navigation"; import { isRedirectError } from "next/dist/client/components/redirect-error"; import { toInternalAdminPath } from "@/lib/admin-routing"; import { clearAdminSessionCookie, isAdminAuthenticated } from "@/lib/admin-auth"; import { isCheckedFormValue } from "@/lib/form-data"; import { getContactProtectionSettings, updateContactProtectionSettings, } from "@/lib/app-config"; import type { ContactProtectionSettings } from "@/lib/contact-protection"; async function ensureAdmin() { if (!(await isAdminAuthenticated())) { await clearAdminSessionCookie(); redirect("/"); } } function withMessage(pathname: string, type: "success" | "error", message: string) { const params = new URLSearchParams(); params.set(type, message); return `${pathname}?${params.toString()}`; } function parseCount(value: string, fallback: number, label: string) { const parsed = Number.parseInt(value || String(fallback), 10); if (!Number.isInteger(parsed) || parsed <= 0) { throw new Error(`${label} must be a positive number.`); } return parsed; } function parseContactProtectionFormData( formData: FormData, existingSettings: ContactProtectionSettings, ): ContactProtectionSettings { const turnstileEnabled = isCheckedFormValue(formData.get("turnstileEnabled")); const turnstileSiteKey = String(formData.get("turnstileSiteKey") ?? "").trim(); const turnstileSecretKey = String(formData.get("turnstileSecretKey") ?? ""); const rateLimitEnabled = isCheckedFormValue(formData.get("contactRateLimitEnabled")); if (turnstileEnabled && !turnstileSiteKey) { throw new Error("Turnstile site key is required when Turnstile is enabled."); } if (turnstileEnabled && !turnstileSecretKey.trim() && !existingSettings.turnstile.secretKey) { throw new Error("Turnstile secret key is required when Turnstile is enabled."); } return { turnstile: { enabled: turnstileEnabled, siteKey: turnstileSiteKey, secretKey: turnstileSecretKey.trim() ? turnstileSecretKey : existingSettings.turnstile.secretKey, }, rateLimit: { enabled: rateLimitEnabled, maxRequests: parseCount( String(formData.get("contactRateLimitMaxRequests") ?? ""), existingSettings.rateLimit.maxRequests, "Rate limit max requests", ), windowMinutes: parseCount( String(formData.get("contactRateLimitWindowMinutes") ?? ""), existingSettings.rateLimit.windowMinutes, "Rate limit window minutes", ), }, }; } export async function saveContactProtectionSettingsAction(formData: FormData) { await ensureAdmin(); try { const existingSettings = await getContactProtectionSettings(); const nextSettings = parseContactProtectionFormData(formData, existingSettings); await updateContactProtectionSettings(nextSettings); revalidatePath(toInternalAdminPath("/smtp/contact-protection")); revalidatePath("/contact"); revalidatePath("/ar/contact"); revalidatePath("/en/contact"); redirect( withMessage( "/smtp/contact-protection", "success", "Contact Protection gespeichert.", ), ); } catch (error) { if (isRedirectError(error)) { throw error; } const message = error instanceof Error ? error.message : "Contact Protection konnte nicht gespeichert werden."; redirect(withMessage("/smtp/contact-protection", "error", message)); } }