Commit Graph

4 Commits

Author SHA1 Message Date
schalli 39aa4bff2a feat(ldap): allow testing connection before saving a config
Tessera CI/CD / Lint & Type Check (push) Successful in 43s
Tessera CI/CD / Tests (push) Successful in 42s
Tessera CI/CD / Build & Publish Images (push) Successful in 1m35s
"Verbindung testen" only appeared after a config was already saved,
so a fresh/never-configured tenant had no way to validate connection
details at all. Now the button is always visible; POST /ldap/test-connection
accepts optional ad-hoc serverUrl/bindDn/bindPassword and falls back
field-by-field to the saved config for anything omitted (bindPassword
in particular, since the form never re-sends the masked saved password).

Verified locally: tested with typed-but-unsaved values (base DN left
blank, nothing saved) and got a real connection attempt/error back,
not a 404 "no config" response.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-08 10:55:46 +02:00
schalli a5c500dbb3 fix(ldap): remove DTO default initializers that clobbered partial updates
CreateLdapConfigDto's optional fields (searchFilter, syncIntervalMin,
isActive, groupFilterDns) had class-field default initializers.
NestJS's ValidationPipe instantiates DTOs via plainToInstance, which
applies those defaults even when the field is absent from the request
body -- so any partial PATCH not including a given field silently
reset it to the hardcoded default instead of leaving it untouched.

Caught by testing the new groupFilterDns-only PATCH: saving the group
filter alone reset searchFilter back to "(objectClass=person)",
clobbering the configured Active Directory filter. The service layer
already has its own `?? default` fallback for create, so the DTO
initializers were redundant and unsafe. Removing them makes updateConfig's
existing "only set if dto.field !== undefined" pattern behave correctly
for every optional field, not just the ones sent together in one request.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-07 09:57:24 +02:00
schalli 3c057f863d feat(ldap): add groupFilterDns column for selective import filter
Persists per-tenant AD group/OU DNs to restrict which directory
entries get synced. Empty array (default) preserves current
behavior — import everyone under base DN.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-07 09:34:27 +02:00
schalli f928cd7713 feat(02-04): LdapModule with sync service, config service, scheduler, and controller
- LdapService uses ldapts for DIRECTORY SYNC ONLY (anti-pattern avoidance)
- LdapConfigService creates default field mappings per D-16 (displayName, mail, sAMAccountName)
- Custom field mappings can be added/removed per D-17
- Per-tenant LDAP config per D-18
- syncUsersForTenant deactivates users removed from LDAP per D-15
- LdapSyncScheduler sets tenant context explicitly per Pitfall 2
- Manual sync endpoint POST /ldap/sync per D-14
- Auto-sync cron checks syncIntervalMin per D-14
- Test connection endpoint for LDAP config validation
- OpenLDAP + phpLDAPadmin added to docker-compose.dev.yml
- LDAP search filter sanitization per T-02-16
- bindPassword never returned in API responses per T-02-17
2026-06-19 08:38:07 +02:00