feat(ldap): group/OU discovery endpoint + selective sync filter

Adds listGroups() to browse AD groups/OUs under base DN, and
collectSearchEntries() to restrict syncUsersForTenant to members of
selected groups or users under selected OUs. Group DNs are matched
via escaped memberOf clauses (RFC 4515); OU DNs become extra search
bases. Empty groupFilterDns keeps the original single-base-DN search
unchanged. Controller sync endpoint and the sync scheduler both pass
groupFilterDns through so manual and scheduled syncs honor it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-07 09:36:58 +02:00
parent 3c057f863d
commit 04fc33fc2a
3 changed files with 154 additions and 6 deletions
+26
View File
@@ -131,6 +131,31 @@ export class LdapController {
});
}
/**
* GET /ldap/groups - Discover AD groups/OUs under the configured base DN,
* for building a selective import filter (groupFilterDns).
*/
@Get('groups')
@Roles(Role.ADMIN, Role.SUPER_ADMIN)
async listGroups(@Req() req: any) {
const tenantId = req.tenantId;
if (!tenantId) {
throw new BadRequestException('No tenant context');
}
const config = await this.ldapConfigService.getConfig(tenantId);
if (!config) {
throw new NotFoundException('No LDAP config found for this tenant');
}
return this.ldapService.listGroups({
serverUrl: config.serverUrl,
baseDn: config.baseDn,
bindDn: config.bindDn,
bindPassword: config.bindPassword,
});
}
/**
* POST /ldap/sync - Trigger manual sync (D-14 "LDAP synchronisieren" button).
* Returns sync results with created/updated/deactivated counts.
@@ -157,6 +182,7 @@ export class LdapController {
bindDn: config.bindDn,
bindPassword: config.bindPassword,
searchFilter: config.searchFilter,
groupFilterDns: config.groupFilterDns,
fieldMappings: config.fieldMappings,
},
tenantId,