feat(16-01): tracer — select and import AD groups end-to-end
Task 1 checkpoint resolved: approve-both, granted 2026-08-06 by the
project owner (D-04 one-way schema extension: Group.internalName +
Group.ldapObjectGuid, both nullable, one versioned migration).
Adds the Phase 16 tracer slice through every layer:
- Prisma schema: Group.internalName, Group.ldapObjectGuid,
@@unique([tenantId, ldapObjectGuid]) (Prisma client regenerated;
the versioned migration itself is Task 3, separately blocking).
- LdapService: listGroups() now reads objectGUID via
explicitBufferAttributes and flags alreadyImported per tenant;
new importGroupsByDn() creates a Group per checked DN with
name/ldapDn/ldapObjectGuid, reject-with-report on name collision
(P2002 on name -> nameCollisions, P2002 on ldapObjectGuid ->
skipped), never aborts the batch on one DN's error; new static
escapeLdapFilterBuffer() for Plan 16-03's later existence sweep.
- DTO/controller: ImportGroupsDto, POST /ldap/groups/import
(ADMIN/SUPER_ADMIN), listGroups route now tenant-scoped.
- Frontend: new "AD-Gruppen importieren" section in /admin/ldap,
own discovery/import handlers with a visible error state
(Owner decision 2026-08-06 — no silent catch{} for these two
handlers), i18n keys in de.json/en.json.
- Tests: 8 new cases covering the full <behavior> list plus
listGroups sort order and alreadyImported.
Flagged assumption (RESEARCH.md A1/A2): objectGUID rename-stability
and the binary filter syntax are unverified against a real AD —
this plan only WRITES the GUID, Plan 16-03 reads it back live.
This commit is contained in:
@@ -346,6 +346,21 @@
|
||||
"emptyMeansAll": "Keine Auswahl - alle Benutzer unter den Basis-DN(s) werden synchronisiert.",
|
||||
"save": "Filter speichern"
|
||||
},
|
||||
"groupImport": {
|
||||
"title": "AD-Gruppen importieren",
|
||||
"description": "Ausgewählte AD-Gruppen werden als Tessera-Gruppen angelegt und danach bei jeder Synchronisation automatisch nachgeführt — Name, Mitgliedschaft und Löschung im AD ziehen nach.",
|
||||
"discover": "AD-Gruppen suchen",
|
||||
"searchPlaceholder": "AD-Gruppen durchsuchen...",
|
||||
"noneFound": "Keine AD-Gruppen gefunden.",
|
||||
"noMatches": "Keine Treffer für diese Suche.",
|
||||
"alreadyImported": "Bereits importiert",
|
||||
"importSelected": "Ausgewählte importieren",
|
||||
"resultSummary": "{imported} importiert, {skipped} übersprungen{errors, plural, =0 {} other {, # Fehler}}",
|
||||
"membershipHint": "Mitgliedschaften werden beim nächsten Sync-Lauf automatisch befüllt (manuell oder nach Intervall).",
|
||||
"nameCollisionError": "Gruppe „{name}\" konnte nicht importiert werden: Der Name ist bereits vergeben. Benenne die bestehende lokale Gruppe um oder vergib ihr einen internen Namen.",
|
||||
"discoverError": "AD-Gruppen konnten nicht abgerufen werden. Prüfe die LDAP-Verbindung und versuche es erneut.",
|
||||
"importError": "Der Import konnte nicht ausgeführt werden. Es wurde keine Gruppe angelegt."
|
||||
},
|
||||
"userExclude": {
|
||||
"title": "Benutzer ausschliessen (Denylist)",
|
||||
"description": "Einzelne Benutzernamen, die nie importiert werden - z. B. Dienstkonten wie administrator, krbtgt, guest oder ldap$. Wirkt zusaetzlich zum Gruppen-/OU-Filter.",
|
||||
|
||||
Reference in New Issue
Block a user