feat(verzeichnis): LDAP-Abgleich, Zeitplan, CSV-Import und Log
Prüfung / pruefung (push) Canceled after 0s
Prüfung / pruefung (pull_request) Canceled after 0s
Prüfung / e2e (push) Canceled after 0s
Prüfung / e2e (pull_request) Canceled after 0s

Quelle anlegen, Verbindung testen, nach Zeitplan oder auf Knopfdruck
abgleichen. Gelesen wird seitenweise mit searchPaginated, objectGUID
kommt als Puffer und wird gemischt-endian zur GUID umsortiert. Wer im
Verzeichnis verschwindet, wird hier inaktiv und nie geloescht.

Drei Regeln verhindern, dass eine kaputte Eingabe wie "alle sind
gegangen" aussieht: laesst sich kein einziger Eintrag zuordnen, wird
niemand deaktiviert; uebersprungene Eintraege werden am dn erkannt und
ausgenommen; eine von Hand angelegte Person wird uebernommen statt
verdoppelt.

Der Zeitplan laeuft ueber node-cron im selben Prozess, gestartet aus
src/instrumentation.ts, und nimmt keine eigene Sperre - die liegt in der
Datenbank, damit zwei Instanzen sich einig sind.

Closes #16

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Florian Wilde
2026-09-26 02:21:08 +02:00
co-authored by Claude Opus 5
parent ab5777a57e
commit 16059e7846
57 changed files with 6834 additions and 61 deletions
+23
View File
@@ -130,6 +130,29 @@ zugeordnet. Unbekannte Benutzer werden beim ersten Login angelegt.
Die Anbindung an authentik ist in [`docs/betrieb/authentik.md`](docs/betrieb/authentik.md)
Schritt für Schritt beschrieben.
## Verzeichnis-Abgleich (nur Modus `INTERN`)
Unter **Admin → Verzeichnis** wird eine LDAP-Quelle angelegt: Adresse (`ldaps://` empfohlen,
`ldap+starttls://` und `ldap://` gehen auch), ein Dienstkonto mit **Leserecht**, der Basis-DN und
optional ein eigener Filter. Ein Dienstkonto genügt — Laufzettel schreibt nie ins Verzeichnis.
- **„Verbindung testen“** liest die ersten Einträge und zeigt sie **mit den gemappten Feldern**,
ohne etwas zu speichern. Erst daran sieht man, ob die Zuordnung stimmt.
- **Die Attributzuordnung** ist einklappbar im Formular und trägt die AD-Vorgaben; ein OpenLDAP
bekommt hier etwa `entryUUID` als Kennung.
- **Der Zeitplan** läuft im selben Prozess wie die Anwendung und sieht jede Minute nach, welche
Quelle fällig ist; das Intervall steht je Quelle. `ZEITPLAN_AKTIV=false` schaltet ihn ab — für
Einmal-Container, die nur Migrationen fahren.
- **Gelöscht wird nie.** Wer im Verzeichnis verschwindet oder deaktiviert wird, wird hier inaktiv.
Lässt sich **kein einziger** Eintrag zuordnen, deaktiviert der Abgleich niemanden und meldet
stattdessen einen Fehler — ein falsch gesetztes Kennungsattribut soll nicht die halbe Firma
abschalten.
- **Das Bind-Passwort** wird verschlüsselt gespeichert und nie wieder angezeigt; ein leeres Feld
beim Bearbeiten heißt „unverändert“.
Ohne Verzeichnis geht es auch: Personen lassen sich von Hand anlegen oder aus einer CSV-Datei
einlesen.
## Umgebungsvariablen
Alle Variablen mit Erklärung stehen in [`.env.example`](.env.example). Pflicht sind `APP_URL`,