"use server"; import { revalidatePath } from "next/cache"; import { z } from "@/lib/validierung"; import { akteurVon } from "@/server/actions/formular"; import { darf } from "@/server/auth/rechte"; import { BestaetigungFehler, RechteFehler, rechtErforderlich } from "@/server/auth/sitzungspflicht"; import { FachFehler } from "@/server/services/fachfehler"; import { rotationAbbrechen, rotationAltWiderrufen, rotationStarten, rotationUebernehmen, } from "@/server/services/rotation"; import { VerwendungsFehler } from "@/server/services/verwendungen"; /** * Gefuehrte Rotation (#023): je Schritt eine duenne Aktion, die Oberflaeche verkettet sie. * Rotieren heisst einen Schluessel erzeugen und ausrollen: `schluesselVerwalten` und * `publicKeyAusrollen`; fuer Private-Key-Zuweisungen zusaetzlich `privateKeyAusrollen` (Service). */ export type RotationsAntwort = { readonly vorgangId?: string; readonly fehler?: string }; function alsAntwort(fehler: unknown): RotationsAntwort { if ( fehler instanceof RechteFehler || fehler instanceof BestaetigungFehler || fehler instanceof VerwendungsFehler || fehler instanceof FachFehler ) { return { fehler: fehler.message }; } throw fehler; } const id = z.string().min(1).max(64); async function berechtigt() { await rechtErforderlich("schluesselVerwalten"); return rechtErforderlich("publicKeyAusrollen"); } export async function rotationStartenAktion(schluesselId: string): Promise { try { const { benutzer } = await berechtigt(); return { vorgangId: await rotationStarten(id.parse(schluesselId), akteurVon(benutzer)) }; } catch (fehler) { return alsAntwort(fehler); } } export async function rotationUebernehmenAktion(schluesselId: string): Promise { try { const { benutzer } = await berechtigt(); await rotationUebernehmen(id.parse(schluesselId), akteurVon(benutzer), { privatErlaubt: darf(benutzer.rolle, "privateKeyAusrollen"), }); revalidatePath(`/schluessel/${schluesselId}`); return {}; } catch (fehler) { return alsAntwort(fehler); } } export async function rotationAltWiderrufenAktion(schluesselId: string): Promise { try { const { benutzer } = await berechtigt(); await rotationAltWiderrufen(id.parse(schluesselId), akteurVon(benutzer), { privatErlaubt: darf(benutzer.rolle, "privateKeyAusrollen"), }); revalidatePath(`/schluessel/${schluesselId}`); return {}; } catch (fehler) { return alsAntwort(fehler); } } /** * Laufende Rotation abbrechen (#032): merkt den neuen Schluessel zum Widerruf vor. Gleiche Rechte * wie die Rotation selbst; Private Keys entfernt nur, wer sie ausrollen darf (Service). */ export async function rotationAbbrechenAktion(schluesselId: string): Promise { try { const { benutzer } = await berechtigt(); const altId = id.parse(schluesselId); await rotationAbbrechen(altId, akteurVon(benutzer), { privatErlaubt: darf(benutzer.rolle, "privateKeyAusrollen"), }); revalidatePath(`/schluessel/${altId}`); revalidatePath(`/schluessel/${altId}/rotieren`); return {}; } catch (fehler) { return alsAntwort(fehler); } }