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>
75 lines
3.2 KiB
TypeScript
75 lines
3.2 KiB
TypeScript
import type { Metadata } from "next";
|
||
import { redirect } from "next/navigation";
|
||
import { AnmeldeRahmen } from "@/components/anmeldung/AnmeldeRahmen";
|
||
import { KontoFormular } from "@/components/anmeldung/KontoFormular";
|
||
import { buttonKlassen, Formularfehler } from "@/components/ui";
|
||
import { lokaleKontenAktiv } from "@/lib/lokale-konten";
|
||
import { sicheresZiel } from "@/server/auth/anmeldung";
|
||
import { oidcAktiv, oidcName } from "@/server/auth/oidc";
|
||
import { angemeldet } from "@/server/auth/sitzungspflicht";
|
||
|
||
export const metadata: Metadata = { title: "Anmelden" };
|
||
|
||
/** Codes aus /api/auth/oidc/rueckruf – nie der Meldungstext selbst in der Adresse. */
|
||
const FEHLER: Record<string, string> = {
|
||
"oidc-aus": "Die Anmeldung über den Identitätsanbieter ist nicht eingerichtet.",
|
||
"oidc-start": "Der Identitätsanbieter ist nicht erreichbar. Bitte später erneut versuchen.",
|
||
"oidc-rueckruf": "Die Anmeldung beim Identitätsanbieter ist fehlgeschlagen. Bitte erneut versuchen.",
|
||
"keine-gruppe":
|
||
"Ihr Konto ist keiner SSHKeyVault-Gruppe zugeordnet. Bitte beim Administrator Zugriff beantragen.",
|
||
"konto-konflikt":
|
||
"Für diese E-Mail-Adresse besteht bereits ein anderes Konto. Bitte den Administrator ansprechen.",
|
||
deaktiviert: "Dieses Konto ist deaktiviert.",
|
||
"fremdes-konto": "Die Bestätigung kam von einem anderen Konto als dem angemeldeten.",
|
||
allgemein: "Die Anmeldung ist fehlgeschlagen.",
|
||
};
|
||
|
||
export default async function AnmeldenSeite({
|
||
searchParams,
|
||
}: {
|
||
searchParams: Promise<{ ziel?: string; fehler?: string; abgemeldet?: string }>;
|
||
}) {
|
||
const parameter = await searchParams;
|
||
const ziel = sicheresZiel(parameter.ziel);
|
||
if (await angemeldet()) redirect(ziel);
|
||
|
||
const oidc = oidcAktiv();
|
||
const lokal = lokaleKontenAktiv();
|
||
const fehler = parameter.fehler ? (FEHLER[parameter.fehler] ?? FEHLER["allgemein"]) : undefined;
|
||
|
||
return (
|
||
<AnmeldeRahmen
|
||
titel="Anmelden"
|
||
text={parameter.abgemeldet ? "Sie wurden abgemeldet." : "Zentrale Verwaltung von SSH-Schlüsseln."}
|
||
>
|
||
<div className="flex flex-col gap-5">
|
||
<Formularfehler text={fehler} />
|
||
{oidc ? (
|
||
// Ein echter Link statt next/link: die Route leitet zum Anbieter weiter, ein
|
||
// Vorladen durch den Router wuerde einen Anmeldefluss anstossen.
|
||
<a
|
||
href={`/api/auth/oidc/start?ziel=${encodeURIComponent(ziel)}`}
|
||
className={buttonKlassen("primaer", false, "w-full")}
|
||
>
|
||
Mit {oidcName()} anmelden
|
||
</a>
|
||
) : (
|
||
<p className="text-muted text-[14px]">
|
||
{lokal
|
||
? "Kein Identitätsanbieter eingerichtet – Anmeldung mit lokalem Konto."
|
||
: "Kein Identitätsanbieter eingerichtet – nur der Notfallzugang ist aktiv."}
|
||
</p>
|
||
)}
|
||
<details className="group border-border rounded-box border" open={!oidc}>
|
||
<summary className="text-muted hover:text-text flex min-h-11 cursor-pointer items-center px-4 text-[14px] font-medium">
|
||
{lokal ? "Lokales Konto oder Notfallzugang" : "Notfallzugang"}
|
||
</summary>
|
||
<div className="border-border border-t p-4">
|
||
<KontoFormular ziel={ziel} lokal={lokal} />
|
||
</div>
|
||
</details>
|
||
</div>
|
||
</AnmeldeRahmen>
|
||
);
|
||
}
|