feat(anmeldung): lokale Benutzerkonten mit Pflicht-TOTP (#035)
Ohne authentik gab es nur den Notfall-Admin – ein geteiltes Konto ohne Rollen und ohne erkennbare Akteure im Audit-Log. Admins legen jetzt lokale Konten an; sshkv erzeugt ein Einmal-Passwort, das bei der ersten Anmeldung ersetzt wird, danach ist TOTP Pflicht. Rollen, Sperren (beendet Sitzungen sofort) und Zurücksetzen unter Einstellungen → Benutzer, nur für Admins mit frischer Bestätigung. SSHKV_LOKALE_KONTEN=0 schaltet lokale Konten ab; der Notfall-Admin bleibt. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
"use client";
|
||||
|
||||
import { UserPlus } from "lucide-react";
|
||||
import { useActionState } from "react";
|
||||
import { EinmalPasswort } from "@/components/benutzer/EinmalPasswort";
|
||||
import { Auswahlliste, Button, Feld, Formularfehler } from "@/components/ui";
|
||||
import { kontoAnlegenAktion, type KontoZustand } from "@/server/actions/benutzer";
|
||||
|
||||
/** Lokales Konto anlegen (#035). Das Passwort waehlt nicht der Admin, sshkv erzeugt es. */
|
||||
export function KontoAnlegen() {
|
||||
const [zustand, aktion, laeuft] = useActionState<KontoZustand, FormData>(kontoAnlegenAktion, {});
|
||||
return (
|
||||
<div className="flex flex-col gap-4">
|
||||
{zustand.einmalPasswort && zustand.anmeldename && (
|
||||
<EinmalPasswort anmeldename={zustand.anmeldename} passwort={zustand.einmalPasswort} />
|
||||
)}
|
||||
<form action={aktion} className="grid gap-4 sm:grid-cols-[1fr_1fr_12rem_auto] sm:items-end">
|
||||
<div className="sm:col-span-4 empty:hidden">
|
||||
<Formularfehler text={zustand.fehler} />
|
||||
</div>
|
||||
<Feld
|
||||
beschriftung="Anmeldename"
|
||||
name="anmeldename"
|
||||
autoComplete="off"
|
||||
required
|
||||
mono
|
||||
fehler={zustand.feldfehler?.["anmeldename"]}
|
||||
/>
|
||||
<Feld
|
||||
beschriftung="Name"
|
||||
name="name"
|
||||
autoComplete="off"
|
||||
required
|
||||
fehler={zustand.feldfehler?.["name"]}
|
||||
/>
|
||||
<Auswahlliste beschriftung="Rolle" name="rolle" defaultValue="LESER">
|
||||
<option value="LESER">Leser</option>
|
||||
<option value="OPERATOR">Operator</option>
|
||||
<option value="ADMIN">Admin</option>
|
||||
</Auswahlliste>
|
||||
<Button type="submit" variante="primaer" disabled={laeuft} icon={<UserPlus className="size-4" />}>
|
||||
{laeuft ? "Lege an …" : "Konto anlegen"}
|
||||
</Button>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user