"use client"; import { useActionState, useState } from "react"; import { KeyRound, Save, Server, ShieldAlert, ShieldCheck } from "lucide-react"; import { FELD, KAESTCHEN } from "@/lib/formular"; import { AD_ZUORDNUNG, INTERVALL_HOECHSTENS, INTERVALL_MINDESTENS, ZUORDNUNGS_BESCHRIFTUNG, ZUORDNUNGS_FELDER, } from "@/lib/verzeichnis"; import { quelleAnlegenAktion, quelleBearbeitenAktion, type AktionsErgebnis, } from "@/server/actions/verzeichnis"; import type { QuellenSicht } from "@/server/services/verzeichnis"; /** * Anlegen und Bearbeiten einer Verzeichnisquelle (#016). * * Ein Formular für beides, weil es dieselben Felder sind — mit einem * Unterschied, der zählt: **beim Bearbeiten bleibt das Passwortfeld leer, und * leer heißt „unverändert“.** Die Anwendung gibt das gespeicherte Passwort * nirgends heraus; würde ein leeres Feld als Löschung verstanden, nähme jede * Namensänderung der Quelle ihre Anmeldung. */ export function QuelleFormular({ quelle }: { quelle?: QuellenSicht }) { const bearbeiten = quelle !== undefined; const [ergebnis, aktion, laeuft] = useActionState( bearbeiten ? quelleBearbeitenAktion : quelleAnlegenAktion, {}, ); const [zertifikatOffen, setzeZertifikatOffen] = useState(false); const [zuordnungOffen, setzeZuordnungOffen] = useState(false); const [adresse, setzeAdresse] = useState(quelle?.url ?? ""); const klartext = adresse.trim().startsWith("ldap://"); return (
{bearbeiten ? : null} {/* * Die Erklärung steht **außerhalb** des `label` und hängt über * `aria-describedby` am Feld. Im `label` wäre sie Teil des Feldnamens: * ein Screenreader läse „Adresse Drei Formen: ldaps:// …“ als Bezeichnung * des Eingabefelds, und kein Werkzeug fände das Feld noch über seinen * Namen. */}
setzeAdresse(ereignis.target.value)} required aria-describedby="quelle-url-hinweis" placeholder="ldaps://dc01.firma.local:636" className={`${FELD} mono`} /> Drei Formen: ldaps:// (verschlüsselt ab dem ersten Byte, die richtige Wahl), ldap+starttls:// (unverschlüsselt verbunden und dann hochgestuft) und ldap://. {klartext ? ( /* * Die Warnung erscheint erst, wenn sie zutrifft — eine, die immer * dasteht, liest nach dem dritten Mal niemand mehr. */ ) : null}
{bearbeiten ? "Leer lassen behält das gespeicherte Passwort." : "Wird verschlüsselt gespeichert und nie wieder angezeigt."}
Leer lassen nimmt den Standard: aktive Personenkonten. Er schließt deaktivierte Konten aus — wer aus dem Ergebnis verschwindet, wird hier deaktiviert und nie gelöscht.
{/* * Die Attributzuordnung ist einklappbar, aber vollständig da. Vorher stand * sie nur in der Datenbank: der Kommentar im Code versprach „wer ein * OpenLDAP anbindet, ändert einzelne Zeilen“, und genau das ging über die * Oberfläche nicht (Reviewbefund zu #016). */}
setzeZuordnungOffen(e.currentTarget.open)}> Attributzuordnung anpassen

Die Vorgaben sind die Attributnamen eines Active Directory. Ein OpenLDAP heißt an einigen Stellen anders — dort ist die dauerhafte Kennung etwa entryUUID.

{ZUORDNUNGS_FELDER.map((feld) => ( ))}

Die Kennung ist das eine Feld, das später nicht mehr geändert werden sollte: an ihr erkennt der Abgleich eine Person wieder. Ein anderer Wert legt beim nächsten Lauf alle neu an.

setzeZertifikatOffen(e.currentTarget.open)}> Eigenes CA-Zertifikat hinterlegen {/* * Der Zertifikatstext selbst kommt nicht zurück in die Oberfläche — nur * die Auskunft, dass eines hinterlegt ist. Ohne diese Zeile sah das * leere Feld beim Bearbeiten aus wie „kein Zertifikat“, und der Hinweis * darunter behauptete es auch (Reviewbefund zu #016). */} {quelle?.caZertifikatVorhanden ? (

) : null}