mirror of
https://github.com/keycloak/keycloak.git
synced 2026-01-25 16:42:34 +00:00
Calling getTopLevelGroups is slow inside GroupLDAPStorageMapper#getLDAPGroupMappingsConverted (#8430)
Closes #14820 --------- Co-authored-by: Michal Hajas <mhajas@redhat.com>
This commit is contained in:
@@ -54,7 +54,6 @@ import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@@ -338,7 +337,9 @@ public class GroupLDAPStorageMapper extends AbstractLDAPStorageMapper implements
|
||||
|
||||
private void dropNonExistingKcGroups(RealmModel realm, SynchronizationResult syncResult, Set<String> visitedGroupIds) {
|
||||
// Remove keycloak groups, which don't exist in LDAP
|
||||
getAllKcGroups(realm)
|
||||
GroupModel parent = getKcGroupsPathGroup(realm);
|
||||
|
||||
getAllKcGroups(realm, parent)
|
||||
.filter(kcGroup -> !visitedGroupIds.contains(kcGroup.getId()))
|
||||
.forEach(kcGroup -> {
|
||||
logger.debugf("Removing Keycloak group '%s', which doesn't exist in LDAP", kcGroup.getName());
|
||||
@@ -361,22 +362,22 @@ public class GroupLDAPStorageMapper extends AbstractLDAPStorageMapper implements
|
||||
}
|
||||
|
||||
|
||||
protected GroupModel findKcGroupByLDAPGroup(RealmModel realm, LDAPObject ldapGroup) {
|
||||
protected GroupModel findKcGroupByLDAPGroup(RealmModel realm, GroupModel parent, LDAPObject ldapGroup) {
|
||||
String groupNameAttr = config.getGroupNameLdapAttribute();
|
||||
String groupName = ldapGroup.getAttributeAsString(groupNameAttr);
|
||||
|
||||
if (config.isPreserveGroupsInheritance()) {
|
||||
// Override if better effectivity or different algorithm is needed
|
||||
return getAllKcGroups(realm)
|
||||
return getAllKcGroups(realm, parent)
|
||||
.filter(group -> Objects.equals(group.getName(), groupName)).findFirst().orElse(null);
|
||||
} else {
|
||||
// Without preserved inheritance, it's always at groups path
|
||||
return KeycloakModelUtils.findGroupByPath(realm, getKcGroupPathFromLDAPGroupName(groupName));
|
||||
return session.groups().getGroupByName(realm, parent, groupName);
|
||||
}
|
||||
}
|
||||
|
||||
protected GroupModel findKcGroupOrSyncFromLDAP(RealmModel realm, LDAPObject ldapGroup, UserModel user) {
|
||||
GroupModel kcGroup = findKcGroupByLDAPGroup(realm, ldapGroup);
|
||||
protected GroupModel findKcGroupOrSyncFromLDAP(RealmModel realm, GroupModel parent, LDAPObject ldapGroup, UserModel user) {
|
||||
GroupModel kcGroup = findKcGroupByLDAPGroup(realm, parent, ldapGroup);
|
||||
|
||||
if (kcGroup == null) {
|
||||
|
||||
@@ -385,7 +386,7 @@ public class GroupLDAPStorageMapper extends AbstractLDAPStorageMapper implements
|
||||
// Better to sync all groups from LDAP with preserved inheritance
|
||||
if (!syncFromLDAPPerformedInThisTransaction) {
|
||||
syncDataFromFederationProviderToKeycloak(realm);
|
||||
kcGroup = findKcGroupByLDAPGroup(realm, ldapGroup);
|
||||
kcGroup = findKcGroupByLDAPGroup(realm, parent, ldapGroup);
|
||||
}
|
||||
} else {
|
||||
String groupNameAttr = config.getGroupNameLdapAttribute();
|
||||
@@ -656,14 +657,16 @@ public class GroupLDAPStorageMapper extends AbstractLDAPStorageMapper implements
|
||||
if (mode == LDAPGroupMapperMode.IMPORT && isCreate) {
|
||||
|
||||
List<LDAPObject> ldapGroups = getLDAPGroupMappings(ldapUser);
|
||||
if (!ldapGroups.isEmpty()) {
|
||||
GroupModel parent = getKcGroupsPathGroup(realm);
|
||||
// Import role mappings from LDAP into Keycloak DB
|
||||
for (LDAPObject ldapGroup : ldapGroups) {
|
||||
|
||||
// Import role mappings from LDAP into Keycloak DB
|
||||
for (LDAPObject ldapGroup : ldapGroups) {
|
||||
|
||||
GroupModel kcGroup = findKcGroupOrSyncFromLDAP(realm, ldapGroup, user);
|
||||
if (kcGroup != null) {
|
||||
logger.debugf("User '%s' joins group '%s' during import from LDAP", user.getUsername(), kcGroup.getName());
|
||||
user.joinGroup(kcGroup);
|
||||
GroupModel kcGroup = findKcGroupOrSyncFromLDAP(realm, parent, ldapGroup, user);
|
||||
if (kcGroup != null) {
|
||||
logger.debugf("User '%s' joins group '%s' during import from LDAP", user.getUsername(), kcGroup.getName());
|
||||
user.joinGroup(kcGroup);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -760,13 +763,17 @@ public class GroupLDAPStorageMapper extends AbstractLDAPStorageMapper implements
|
||||
}
|
||||
|
||||
List<LDAPObject> ldapGroups = getLDAPGroupMappings(ldapUser);
|
||||
if (!ldapGroups.isEmpty()) {
|
||||
GroupModel parent = getKcGroupsPathGroup(realm);
|
||||
|
||||
cachedLDAPGroupMappings = ldapGroups.stream()
|
||||
.map(ldapGroup -> findKcGroupOrSyncFromLDAP(realm, ldapGroup, this))
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toSet());
|
||||
cachedLDAPGroupMappings = ldapGroups.stream()
|
||||
.map(ldapGroup -> findKcGroupOrSyncFromLDAP(realm, parent, ldapGroup, this))
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
return cachedLDAPGroupMappings.stream();
|
||||
return cachedLDAPGroupMappings.stream();
|
||||
}
|
||||
return Stream.empty();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -783,7 +790,7 @@ public class GroupLDAPStorageMapper extends AbstractLDAPStorageMapper implements
|
||||
* Provides KC group defined as groups path or null (top-level group) if corresponding group is not available.
|
||||
*/
|
||||
protected GroupModel getKcGroupsPathGroup(RealmModel realm) {
|
||||
return config.isTopLevelGroupsPath() ? null : KeycloakModelUtils.findGroupByPath(realm, config.getGroupsPath());
|
||||
return config.isTopLevelGroupsPath() ? null : KeycloakModelUtils.findGroupByPath(session.groups(), realm, config.getGroupsPath());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -813,9 +820,7 @@ public class GroupLDAPStorageMapper extends AbstractLDAPStorageMapper implements
|
||||
/**
|
||||
* Provides a stream of all KC groups (with their sub groups) from groups path configured by the "Groups Path" configuration property.
|
||||
*/
|
||||
protected Stream<GroupModel> getAllKcGroups(RealmModel realm) {
|
||||
GroupModel topParentGroup = getKcGroupsPathGroup(realm);
|
||||
|
||||
protected Stream<GroupModel> getAllKcGroups(RealmModel realm, GroupModel topParentGroup) {
|
||||
Stream<GroupModel> allGroups = realm.getGroupsStream();
|
||||
if (topParentGroup == null) return allGroups;
|
||||
|
||||
|
||||
@@ -304,7 +304,7 @@ public class GroupLDAPStorageMapperFactory extends AbstractLDAPStorageMapperFact
|
||||
LDAPUtils.validateCustomLdapFilter(config.getConfig().getFirst(GroupMapperConfig.GROUPS_LDAP_FILTER));
|
||||
|
||||
String group = new GroupMapperConfig(config).getGroupsPath();
|
||||
if (!GroupMapperConfig.DEFAULT_LDAP_GROUPS_PATH.equals(group) && KeycloakModelUtils.findGroupByPath(realm, group) == null) {
|
||||
if (!GroupMapperConfig.DEFAULT_LDAP_GROUPS_PATH.equals(group) && KeycloakModelUtils.findGroupByPath(session.groups(), realm, group) == null) {
|
||||
throw new ComponentValidationException("ldapErrorMissingGroupsPathGroup");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user