KEYCLOAK-13817 Return local user from LDAPStorageProvider
This commit is contained in:
parent
fed34929ae
commit
fcb0e450a0
4 changed files with 49 additions and 22 deletions
|
@ -237,7 +237,7 @@ public class LDAPStorageProvider implements UserStorageProvider,
|
|||
if (localUser == null) {
|
||||
UserModel imported = importUserFromLDAP(session, realm, ldapUser);
|
||||
searchResults.add(imported);
|
||||
} else if (shouldUserAttributeBeAlwaysReadFromLdap(realm, attrName)) {
|
||||
} else {
|
||||
searchResults.add(proxy(realm, localUser, ldapUser));
|
||||
}
|
||||
}
|
||||
|
@ -246,20 +246,6 @@ public class LDAPStorageProvider implements UserStorageProvider,
|
|||
}
|
||||
}
|
||||
|
||||
private boolean shouldUserAttributeBeAlwaysReadFromLdap(RealmModel realm, String userAttributeName) {
|
||||
List<ComponentModel> mapperModels = realm.getComponents(model.getId(), LDAPStorageMapper.class.getName());
|
||||
return mapperModels.stream().anyMatch(mapperModel -> shouldUserAttributeBeAlwaysReadFromLdap(mapperModel, userAttributeName));
|
||||
}
|
||||
|
||||
private boolean shouldUserAttributeBeAlwaysReadFromLdap(ComponentModel mapperModel, String userAttributeName) {
|
||||
LDAPStorageMapper mapper = mapperManager.getMapper(mapperModel);
|
||||
if (UserAttributeLDAPStorageMapper.class.isAssignableFrom(mapper.getClass())) {
|
||||
UserAttributeLDAPStorageMapper userAttributeMapper = (UserAttributeLDAPStorageMapper) mapper;
|
||||
return userAttributeName.equals(userAttributeMapper.getUserModelAttribute()) && userAttributeMapper.isAlwaysReadValueFromLdap();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean synchronizeRegistrations() {
|
||||
return "true".equalsIgnoreCase(model.getConfig().getFirst(LDAPConstants.SYNC_REGISTRATIONS)) && editMode == UserStorageProvider.EditMode.WRITABLE;
|
||||
}
|
||||
|
|
|
@ -415,7 +415,7 @@ public class UserAttributeLDAPStorageMapper extends AbstractLDAPStorageMapper {
|
|||
}
|
||||
}
|
||||
|
||||
public String getUserModelAttribute() {
|
||||
private String getUserModelAttribute() {
|
||||
return mapperModel.getConfig().getFirst(USER_MODEL_ATTRIBUTE);
|
||||
}
|
||||
|
||||
|
@ -431,10 +431,6 @@ public class UserAttributeLDAPStorageMapper extends AbstractLDAPStorageMapper {
|
|||
return parseBooleanParameter(mapperModel, READ_ONLY);
|
||||
}
|
||||
|
||||
public boolean isAlwaysReadValueFromLdap() {
|
||||
return parseBooleanParameter(mapperModel, ALWAYS_READ_VALUE_FROM_LDAP);
|
||||
}
|
||||
|
||||
protected void setPropertyOnUserModel(Property<Object> userModelProperty, UserModel user, String ldapAttrValue) {
|
||||
if (ldapAttrValue == null) {
|
||||
userModelProperty.setValue(user, null);
|
||||
|
|
|
@ -50,13 +50,16 @@ import org.keycloak.storage.user.UserLookupProvider;
|
|||
import org.keycloak.storage.user.UserQueryProvider;
|
||||
import org.keycloak.storage.user.UserRegistrationProvider;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import static org.keycloak.models.utils.KeycloakModelUtils.runJobInTransaction;
|
||||
|
||||
|
@ -624,9 +627,16 @@ public class UserStorageManager implements UserProvider, OnUserCache, OnCreateCo
|
|||
}
|
||||
return Collections.EMPTY_LIST;
|
||||
}, realm,0, Integer.MAX_VALUE - 1);
|
||||
results = removeDuplicates(results);
|
||||
return importValidation(realm, results);
|
||||
}
|
||||
|
||||
private static List<UserModel> removeDuplicates(List<UserModel> withDuplicates) {
|
||||
Set<UserModel> withoutDuplicates = new TreeSet<>(Comparator.comparing(UserModel::getId));
|
||||
withoutDuplicates.addAll(withDuplicates);
|
||||
return new ArrayList<>(withoutDuplicates);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<FederatedIdentityModel> getFederatedIdentities(UserModel user, RealmModel realm) {
|
||||
if (user == null) throw new IllegalStateException("Federated user no longer valid");
|
||||
|
|
|
@ -24,7 +24,6 @@ import java.util.List;
|
|||
import javax.mail.MessagingException;
|
||||
import javax.mail.internet.MimeMessage;
|
||||
|
||||
import org.hamcrest.Matchers;
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.FixMethodOrder;
|
||||
|
@ -35,6 +34,8 @@ import org.keycloak.component.ComponentModel;
|
|||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.LDAPConstants;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.UserProvider;
|
||||
import org.keycloak.representations.idm.UserRepresentation;
|
||||
import org.keycloak.storage.UserStorageProviderModel;
|
||||
import org.keycloak.storage.ldap.LDAPStorageProvider;
|
||||
|
@ -52,7 +53,12 @@ import org.keycloak.testsuite.util.LDAPRule;
|
|||
import org.keycloak.testsuite.util.LDAPTestUtils;
|
||||
import org.keycloak.testsuite.util.MailUtils;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.not;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assume.assumeThat;
|
||||
|
||||
/**
|
||||
* Test for the scenarios with disabled cache for LDAP provider. This involves scenarios when something is changed directly in LDAP server
|
||||
|
@ -147,7 +153,6 @@ public class LDAPNoCacheTest extends AbstractLDAPTest {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void resetPasswordLinkCheckOldAddressLast() throws IOException, MessagingException {
|
||||
// Trigger reset password from the login page
|
||||
|
@ -211,4 +216,34 @@ public class LDAPNoCacheTest extends AbstractLDAPTest {
|
|||
});
|
||||
}
|
||||
|
||||
// KEYCLOAK-13817
|
||||
@Test
|
||||
public void lookupByAttributeAfterImportWithAttributeValueAlwaysReadFromLdapMustSucceed() {
|
||||
testingClient.server().run(session -> {
|
||||
LDAPTestContext ctx = LDAPTestContext.init(session);
|
||||
RealmModel realm = ctx.getRealm();
|
||||
ctx.getLdapModel().setImportEnabled(true);
|
||||
realm.updateComponent(ctx.getLdapModel());
|
||||
|
||||
UserProvider localStorage = session.userLocalStorage();
|
||||
LDAPStorageProvider ldapProvider = ctx.getLdapProvider();
|
||||
|
||||
// assume no user imported
|
||||
UserModel user = localStorage.getUserByUsername("johnkeycloak", realm);
|
||||
assumeThat(user, is(nullValue()));
|
||||
|
||||
// trigger import
|
||||
List<UserModel> byEmail = ldapProvider.searchForUserByUserAttribute("email", "john_old@email.org", realm);
|
||||
assumeThat(byEmail, hasSize(1));
|
||||
|
||||
// assume that user has been imported
|
||||
user = localStorage.getUserByUsername("johnkeycloak", realm);
|
||||
assumeThat(user, is(not(nullValue())));
|
||||
|
||||
// search a second time
|
||||
byEmail = ldapProvider.searchForUserByUserAttribute("email", "john_old@email.org", realm);
|
||||
assertThat(byEmail, hasSize(1));
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue