Merge branch 'phase/019-vorlagen'

This commit is contained in:
2026-10-12 10:54:31 +02:00
4 changed files with 418 additions and 0 deletions
+73
View File
@@ -0,0 +1,73 @@
"use server";
import { revalidatePath } from "next/cache";
import { redirect } from "next/navigation";
import { VorlagenFehler, type VorlageEingabe } from "@/lib/vorlagen";
import { akteurVon, fehlerZustand, textfeld, type FormularZustand } from "@/server/actions/formular";
import { rechtErforderlich } from "@/server/auth/sitzungspflicht";
import { vorlageAnlegen, vorlageArchivieren, vorlageBearbeiten } from "@/server/services/vorlagen";
/** Vorlagen-Aktionen (#019): nur Admins (Recht einstellungenVerwalten). */
function felder(formular: FormData): VorlageEingabe {
const tage = textfeld(formular, "standardLaufzeitTage");
return {
name: textfeld(formular, "name") ?? "",
beschreibung: textfeld(formular, "beschreibung") ?? null,
schluesselTyp: textfeld(formular, "schluesselTyp") === "RSA4096" ? "RSA4096" : "ED25519",
kategorie: textfeld(formular, "kategorie") === "PERSON" ? "PERSON" : "DIENST",
standardLaufzeitTage: tage ? Number(tage) : null,
zielbenutzer: (textfeld(formular, "zielbenutzer") ?? "").trim(),
zielbenutzerAnlegen: formular.get("zielbenutzerAnlegen") === "ja",
sudoModus:
(["KEINER", "BEFEHLE", "VOLL"] as const).find((m) => m === textfeld(formular, "sudoModus")) ?? "KEINER",
sudoBefehle: (textfeld(formular, "sudoBefehle") ?? "")
.split("\n")
.map((b) => b.trim())
.filter(Boolean),
authorizedKeysOptionen: textfeld(formular, "authorizedKeysOptionen") ?? null,
sshConfigAlias: textfeld(formular, "sshConfigAlias") ?? null,
knownHostsEintragen: formular.get("knownHostsEintragen") === "ja",
privatNachAusrollenLoeschen: formular.get("privatNachAusrollenLoeschen") === "ja",
};
}
function alsZustand(fehler: unknown): FormularZustand {
if (fehler instanceof VorlagenFehler) {
return {
fehler: fehler.message,
...(fehler.feld ? { feldfehler: { [fehler.feld]: fehler.message } } : {}),
};
}
return fehlerZustand(fehler);
}
export async function vorlageSpeichernAktion(
_vorher: FormularZustand,
formular: FormData,
): Promise<FormularZustand> {
const id = textfeld(formular, "id");
try {
const { benutzer } = await rechtErforderlich("einstellungenVerwalten");
if (id) await vorlageBearbeiten(id, felder(formular), akteurVon(benutzer));
else await vorlageAnlegen(felder(formular), akteurVon(benutzer));
} catch (fehler) {
return alsZustand(fehler);
}
revalidatePath("/vorlagen");
redirect("/vorlagen");
}
export async function vorlageArchivierenAktion(
_vorher: FormularZustand,
formular: FormData,
): Promise<FormularZustand> {
try {
const { benutzer } = await rechtErforderlich("einstellungenVerwalten");
await vorlageArchivieren(textfeld(formular, "id") ?? "", akteurVon(benutzer));
} catch (fehler) {
return alsZustand(fehler);
}
revalidatePath("/vorlagen");
redirect("/vorlagen");
}