Files
sshkeyvault/src/server/actions/meine-schluessel.ts
T
florian.wildeandClaude Opus 5.5 b5b43f41f6 feat(personen): Personen und Self-Service Meine Schluessel (#013)
Personen lassen sich anlegen, bearbeiten und archivieren; ihr Detail
zeigt ihre Schluessel. Unter "Meine Schluessel" hinterlegt jede Rolle
eigene Public Keys (Freigabe Frage 4), wirksam erst nach Zuweisung
durch einen Operator oder Admin.

Warum so:
- Die eigene Person entsteht beim ersten Aufruf oder wird verknuepft:
  per benutzerId, sonst per E-Mail - aber nur, wenn der OIDC-Anbieter
  die Adresse bestaetigt hat. Dafuer merkt sich Benutzer jetzt
  emailBestaetigt (Migration); sonst koennte jemand mit selbst
  gewaehlter Adresse die Keys einer fremden Person sehen.
- Die Self-Service-Services nehmen nur den angemeldeten Benutzer und
  leiten die Person selbst ab; fremde Schluessel-IDs gelten als nicht
  vorhanden.
- Entfernen nur fuer eigene, selbst hinterlegte Keys ohne Verwendung,
  bedingt geloescht, damit eine gleichzeitige Zuweisung nicht per
  Cascade verschwindet.
- Archivieren statt Loeschen: wer bis wann welchen Key hatte, bleibt
  nachvollziehbar.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 10:38:55 +02:00

44 lines
1.5 KiB
TypeScript

"use server";
import { revalidatePath } from "next/cache";
import { fehlerZustand, textfeld, type FormularZustand } from "@/server/actions/formular";
import { rechtErforderlich } from "@/server/auth/sitzungspflicht";
import { eigenenPublicKeyHinterlegen, eigenenSchluesselEntfernen } from "@/server/services/meine-schluessel";
/**
* Self-Service (#013). Recht `eigeneSchluesselHinterlegen` hat jede Rolle; der Service
* arbeitet ausschliesslich mit der Person des angemeldeten Kontos.
*/
export type HinterlegenZustand = FormularZustand & { readonly erfolg?: string };
export async function eigenenKeyHinterlegenAktion(
_vorher: HinterlegenZustand,
formular: FormData,
): Promise<HinterlegenZustand> {
try {
const { benutzer } = await rechtErforderlich("eigeneSchluesselHinterlegen");
const neu = await eigenenPublicKeyHinterlegen(benutzer, {
name: textfeld(formular, "name") ?? "",
publicKey: textfeld(formular, "publicKey") ?? "",
});
revalidatePath("/meine-schluessel");
return { erfolg: `Hinterlegt: ${neu.fingerprint}` };
} catch (fehler) {
return fehlerZustand(fehler);
}
}
export async function eigenenKeyEntfernenAktion(
_vorher: FormularZustand,
formular: FormData,
): Promise<FormularZustand> {
try {
const { benutzer } = await rechtErforderlich("eigeneSchluesselHinterlegen");
await eigenenSchluesselEntfernen(benutzer, textfeld(formular, "id") ?? "");
revalidatePath("/meine-schluessel");
return {};
} catch (fehler) {
return fehlerZustand(fehler);
}
}