From bcbb94500d2de2b4f1835d077eae4adbbe33398b Mon Sep 17 00:00:00 2001 From: Schalli Date: Tue, 7 Jul 2026 09:59:21 +0200 Subject: [PATCH] docs(quick-260707-csw): LDAP AD Anbindung: Zugangsdaten aus XWiki vorbefuellen und Import-Filter fuer Benutzer/Gruppen Co-Authored-By: Claude Sonnet 5 --- .planning/STATE.md | 4 ++- .../260707-csw-SUMMARY.md | 29 +++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 .planning/quick/260707-csw-ldap-ad-anbindung-zugangsdaten-aus-xwiki/260707-csw-SUMMARY.md diff --git a/.planning/STATE.md b/.planning/STATE.md index 89de0db..f923847 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -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/) | | 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 @@ -158,6 +159,7 @@ Items acknowledged and carried forward from previous milestone close: ## 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) 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 diff --git a/.planning/quick/260707-csw-ldap-ad-anbindung-zugangsdaten-aus-xwiki/260707-csw-SUMMARY.md b/.planning/quick/260707-csw-ldap-ad-anbindung-zugangsdaten-aus-xwiki/260707-csw-SUMMARY.md new file mode 100644 index 0000000..d54be7a --- /dev/null +++ b/.planning/quick/260707-csw-ldap-ad-anbindung-zugangsdaten-aus-xwiki/260707-csw-SUMMARY.md @@ -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.