"use server"; import { revalidatePath } from "next/cache"; import { redirect } from "next/navigation"; import { createPeopleMutationInvocation, peopleMutationService, } from "@/features/housekeeping/domains/people/services/mutations"; import { createCorrelationId } from "@/features/housekeeping/foundation/contracts"; import { requirePermission } from "@/lib/admin/guard"; import { PERMS } from "@/lib/permissions"; const ALLOWED_PROVIDERS = new Set(["none", "proxycheck", "ipqualityscore"]); export async function saveVpn(formData: FormData): Promise { const staff = await requirePermission(PERMS.SETTINGS_EDIT); const rawProvider = String(formData.get("vpn_provider") ?? "") .normalize("NFC") .trim() .toLowerCase(); const provider = ALLOWED_PROVIDERS.has(rawProvider) ? rawProvider : "none"; const result = await peopleMutationService.execute( createPeopleMutationInvocation(staff, createCorrelationId()), "vpn.configure", { enabled: String(formData.get("vpn_block_enabled") ?? "").trim() !== "", provider, apiKey: String(formData.get("vpn_api_key") ?? "") .normalize("NFC") .trim() .slice(0, 255), blockMessage: String(formData.get("vpn_block_message") ?? "") .normalize("NFC") .trim() .slice(0, 255), }, ); if (result.ok) revalidatePath("/ase/people/moderation/vpn"); // Preserve fail-soft legacy navigation even when persistence is unavailable. redirect("/ase/people/moderation/vpn?saved=1"); }