docs(quick-260707-csw): LDAP AD Anbindung: Zugangsdaten aus XWiki vorbefuellen und Import-Filter fuer Benutzer/Gruppen

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-07 09:59:21 +02:00
parent a5c500dbb3
commit bcbb94500d
2 changed files with 32 additions and 1 deletions
+3 -1
View File
@@ -147,6 +147,7 @@ None yet.
|---|-------------|------|--------|-----------| |---|-------------|------|--------|-----------|
| 260630-gbh | User Settings: Passwort ändern (nur non-LDAP) + Profilbild setzen | 2026-06-30 | merge | [260630-gbh-user-settings-passwort-ndern-nur-non-lda](.planning/quick/260630-gbh-user-settings-passwort-ndern-nur-non-lda/) | | 260630-gbh | User Settings: Passwort ändern (nur non-LDAP) + Profilbild setzen | 2026-06-30 | merge | [260630-gbh-user-settings-passwort-ndern-nur-non-lda](.planning/quick/260630-gbh-user-settings-passwort-ndern-nur-non-lda/) |
| 260701-abc | Fix i18n: marketplace.accessDenied + calendar form hardcoded EN strings | 2026-07-01 | e5b76b7 | [260701-abc-i18n-missing-keys](.planning/quick/260701-abc-i18n-missing-keys/) | | 260701-abc | Fix i18n: marketplace.accessDenied + calendar form hardcoded EN strings | 2026-07-01 | e5b76b7 | [260701-abc-i18n-missing-keys](.planning/quick/260701-abc-i18n-missing-keys/) |
| 260707-csw | LDAP AD Anbindung: Zugangsdaten aus XWiki vorbefuellen und Import-Filter fuer Benutzer/Gruppen | 2026-07-07 | a5c500d | [260707-csw-ldap-ad-anbindung-zugangsdaten-aus-xwiki](.planning/quick/260707-csw-ldap-ad-anbindung-zugangsdaten-aus-xwiki/) |
## Deferred Items ## Deferred Items
@@ -158,6 +159,7 @@ Items acknowledged and carried forward from previous milestone close:
## Session Continuity ## Session Continuity
Last session: 2026-07-02T06:21:54.686Z Last session: 2026-07-07T07:58:00.000Z
Stopped at: context exhaustion at 77% (2026-07-02) Stopped at: context exhaustion at 77% (2026-07-02)
Resume file: .planning/phases/08-dashboard-widgets-vollimplementierung/08-CONTEXT.md Resume file: .planning/phases/08-dashboard-widgets-vollimplementierung/08-CONTEXT.md
Last activity: 2026-07-07 - Completed quick task 260707-csw: LDAP AD Anbindung: Zugangsdaten aus XWiki vorbefuellen und Import-Filter fuer Benutzer/Gruppen
@@ -0,0 +1,29 @@
---
status: complete
---
# Quick Task 260707-csw: LDAP AD Anbindung — Zugangsdaten aus XWiki vorbefuellen und Import-Filter fuer Benutzer/Gruppen
## What shipped
1. **AD connection prefill** — `admin/ldap` page now defaults a brand-new config form to the CTL Active Directory values extracted from `user-files/xwiki.cfg` (server `balios.ctl.local:3268`, base DN `dc=ctl,dc=local`, AD person search filter, down-level bind-DN hint). Password stays blank. Editing an existing config still shows its real saved values (unchanged behavior).
2. **Selective group/OU import filter** — new `groupFilterDns String[]` column on `LdapConfig` (additive migration, empty array = current "import everyone" behavior). `GET /ldap/groups` discovers AD groups/OUs under the base DN; admin can select from the discovered list or add DNs manually; selection persists via `PATCH /ldap/config` and is editable any time post-setup. `syncUsersForTenant` now restricts its directory search to members of selected groups (via escaped `memberOf` clauses) or users under selected OUs (extra search bases), for both manual sync and the scheduled cron sync.
3. **Bugfix caught during manual testing (not in original plan):** `CreateLdapConfigDto`'s optional fields (`searchFilter`, `syncIntervalMin`, `isActive`, `groupFilterDns`) had TS class-field default initializers. NestJS's `ValidationPipe` applies those defaults via `plainToInstance` even when the field is absent from the request body, so any partial PATCH silently reset the other fields to hardcoded defaults. Caught live: saving the group filter alone reset `searchFilter` back to `(objectClass=person)`, clobbering the AD-specific filter. Fixed by removing the initializers — the service layer's own `?? default` fallback already covers create-time defaults.
4. **Pre-existing i18n gap fixed (user-approved scope addition):** the `admin.ldap` message block referenced by the page (`t('title')`, `t('connectionTitle')`, `t('serverUrl')`, etc.) did not exist in `de.json`/`en.json` at all, so the whole page rendered raw translation keys instead of text. Backfilled the full set of keys the page actually uses, in addition to the new group-filter keys.
## Verification performed
- `prisma validate`, `prisma generate`, API `type-check`, API `build` — all green.
- Web `type-check` green; both message JSON files parse.
- Migration applied live via container restart (`Applying migration 20260707090000_add_ldap_group_filter`), confirmed idempotent entrypoint (`prisma migrate deploy`).
- End-to-end manual test via Playwright against the running dev stack:
- Fresh `/admin/ldap` page load shows AD-prefilled connection form, password blank.
- Created a config (test bind DN/password — dev environment, no live AD reachable from this sandbox), confirmed default field mappings (`displayName`, `mail`, `sAMAccountName`) are AD-correct.
- Added a group DN manually, saved the filter, reloaded the page — filter persisted.
- Verified via direct DB query (`SELECT ... FROM "LdapConfig"`) that `groupFilterDns` persisted correctly and, after the DTO fix, that `searchFilter`/`syncIntervalMin`/`isActive` are no longer clobbered by a groupFilterDns-only PATCH.
## Known limitations / follow-ups for the user
- **Not tested against a live AD server** — `balios.ctl.local` is not reachable from this environment. `GET /ldap/groups` discovery and the `memberOf`-filtered sync are implemented per the plan's design and pass all static checks, but have not been exercised against real Active Directory data. Recommend testing `testConnection`, `Gruppen/OUs suchen`, and a real sync once this is deployed somewhere with network access to the CTL AD.
- The dev database now has one `LdapConfig` test row (server/base DN are the real CTL AD values; bind DN/password are placeholders `ctl\testservice` / `testpassword`) with one filter DN saved. Replace the bind credentials with the real service-account before relying on this in a real environment.
- The i18n backfill only covers keys this page actually calls — it does not audit the rest of the app for similar gaps.