"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 { VerwendungsFehler } from "@/server/services/verwendungen"; import { widerrufAbschliessen, widerrufEinleiten, widerrufZielkontenEntfernen, type AbschlussErgebnis, } from "@/server/services/widerruf"; /** * Widerruf und Massenwiderruf (#024). Duenn: Recht, Eingabe, Service. * * Rechte: einen Public Key entfernen darf, wer ausrollen darf; sobald Private Keys betroffen * sind, nur ein Admin (prueft der Service mit `privatErlaubt`). Mehrere Schluessel auf einmal * (Massenwiderruf) und das Entfernen von Zielkonten verlangen Admin mit frischer Bestaetigung. */ export type WiderrufAntwort = { readonly fehler?: string; /** Frische Bestaetigung noetig: die Oberflaeche verlinkt /bestaetigen. */ readonly bestaetigen?: boolean; }; function alsAntwort(fehler: unknown): WiderrufAntwort { if (fehler instanceof BestaetigungFehler) return { bestaetigen: true, fehler: fehler.message }; if (fehler instanceof RechteFehler || fehler instanceof VerwendungsFehler) return { fehler: fehler.message }; throw fehler; } const idListe = z.array(z.string().min(1).max(64)).min(1).max(200); function pfadeNeuLaden(ids: readonly string[]) { revalidatePath("/schluessel"); for (const id of ids) revalidatePath(`/schluessel/${id}`); } export async function widerrufEinleitenAktion(schluesselIds: string[]): Promise { try { const ids = idListe.parse(schluesselIds); const { benutzer } = await rechtErforderlich(ids.length > 1 ? "massenwiderruf" : "publicKeyAusrollen"); await widerrufEinleiten(ids, akteurVon(benutzer), { privatErlaubt: darf(benutzer.rolle, "privateKeyAusrollen"), }); pfadeNeuLaden(ids); return {}; } catch (fehler) { return alsAntwort(fehler); } } export async function widerrufZielkontenAktion( schluesselIds: string[], zielkontoIds: string[], ): Promise { try { const ids = idListe.parse(schluesselIds); const konten = idListe.parse(zielkontoIds); // Ein Benutzer samt Home verschwindet: Admin mit frischer Bestaetigung (#018). const { benutzer } = await rechtErforderlich("zielkontenVerwalten"); return { vorgaenge: await widerrufZielkontenEntfernen(ids, konten, akteurVon(benutzer)) }; } catch (fehler) { return alsAntwort(fehler); } } export async function widerrufAbschliessenAktion( schluesselIds: string[], ): Promise { try { const ids = idListe.parse(schluesselIds); // Abschliessen setzt nur den Status nach dem, was die Datenbank belegt – kein Host-Zugriff. const { benutzer } = await rechtErforderlich("publicKeyAusrollen"); const ergebnisse = await widerrufAbschliessen(ids, akteurVon(benutzer)); pfadeNeuLaden(ids); return { ergebnisse }; } catch (fehler) { return alsAntwort(fehler); } }