Avoid returning duplicated users in LDAP and unsynced

Closes #24141

Signed-off-by: rmartinc <rmartinc@redhat.com>
This commit is contained in:
rmartinc 2023-12-22 11:13:15 +01:00 committed by Marek Posolda
parent 50c49990a6
commit 42f0488d76
2 changed files with 34 additions and 2 deletions

View file

@ -27,6 +27,7 @@ import java.util.LinkedHashSet;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function; import java.util.function.Function;
@ -382,8 +383,13 @@ public class LDAPStorageProvider implements UserStorageProvider,
searchLDAP(realm, search, firstResult, maxResults) : searchLDAP(realm, search, firstResult, maxResults) :
searchLDAPByAttributes(realm, params, firstResult, maxResults); searchLDAPByAttributes(realm, params, firstResult, maxResults);
return StreamsUtil.paginatedStream(result.filter(filterLocalUsers(realm)), firstResult, maxResults) if (model.isImportEnabled()) {
.map(ldapObject -> importUserFromLDAP(session, realm, ldapObject)); result = result.filter(filterLocalUsers(realm));
}
return StreamsUtil.paginatedStream(
result.map(ldapObject -> importUserFromLDAP(session, realm, ldapObject, false))
.filter(Objects::nonNull),
firstResult, maxResults);
} }
@Override @Override
@ -619,6 +625,10 @@ public class LDAPStorageProvider implements UserStorageProvider,
} }
protected UserModel importUserFromLDAP(KeycloakSession session, RealmModel realm, LDAPObject ldapUser) { protected UserModel importUserFromLDAP(KeycloakSession session, RealmModel realm, LDAPObject ldapUser) {
return importUserFromLDAP(session, realm, ldapUser, true);
}
protected UserModel importUserFromLDAP(KeycloakSession session, RealmModel realm, LDAPObject ldapUser, boolean duplicates) {
String ldapUsername = LDAPUtils.getUsername(ldapUser, ldapIdentityStore.getConfig()); String ldapUsername = LDAPUtils.getUsername(ldapUser, ldapIdentityStore.getConfig());
LDAPUtils.checkUuid(ldapUser, ldapIdentityStore.getConfig()); LDAPUtils.checkUuid(ldapUser, ldapIdentityStore.getConfig());
@ -633,6 +643,10 @@ public class LDAPStorageProvider implements UserStorageProvider,
if (UserStorageUtil.userCache(session) != null) { if (UserStorageUtil.userCache(session) != null) {
UserStorageUtil.userCache(session).evict(realm, existingLocalUser); UserStorageUtil.userCache(session).evict(realm, existingLocalUser);
} }
if (!duplicates) {
// if duplicates are not wanted return null
return null;
}
} else { } else {
imported = UserStoragePrivateUtil.userLocalStorage(session).addUser(realm, ldapUsername); imported = UserStoragePrivateUtil.userLocalStorage(session).addUser(realm, ldapUsername);
} }

View file

@ -1182,6 +1182,24 @@ public class LDAPProvidersIntegrationTest extends AbstractLDAPTest {
Assert.assertNotNull(session.users().getUserByUsername(appRealm, "johnkeycloak")); Assert.assertNotNull(session.users().getUserByUsername(appRealm, "johnkeycloak"));
}); });
// change username
testingClient.server().run(session -> {
LDAPTestContext ctx = LDAPTestContext.init(session);
RealmModel appRealm = ctx.getRealm();
UserModel user = session.users().getUserByUsername(appRealm, "johnkeycloak");
// change username locally
user.setUsername("johnkeycloak-renamed");
});
// check user is found just once
List<UserRepresentation> users = testRealm().users().search("johnkeycloak", 0, 2);
Assert.assertEquals("More than one user is found", 1, users.size());
List<ComponentRepresentation> components = testRealm().components().query(
testRealm().toRepresentation().getId(), UserStorageProvider.class.getName(), "test-ldap");
Assert.assertEquals("LDAP component not found", 1, users.size());
Assert.assertEquals(components.iterator().next().getId(), users.iterator().next().getFederationLink());
// Revert // Revert
testingClient.server().run(session -> { testingClient.server().run(session -> {
LDAPTestContext ctx = LDAPTestContext.init(session); LDAPTestContext ctx = LDAPTestContext.init(session);