diff --git a/model/api/src/main/java/org/keycloak/models/UserFederationManager.java b/model/api/src/main/java/org/keycloak/models/UserFederationManager.java index fd4569ba20..13c05f8908 100755 --- a/model/api/src/main/java/org/keycloak/models/UserFederationManager.java +++ b/model/api/src/main/java/org/keycloak/models/UserFederationManager.java @@ -314,8 +314,8 @@ public class UserFederationManager implements UserProvider { } @Override - public List searchForUserByUserAttributes(Map attributes, RealmModel realm) { - return session.userStorage().searchForUserByUserAttributes(attributes, realm); + public List searchForUserByUserAttribute(String attrName, String attrValue, RealmModel realm) { + return session.userStorage().searchForUserByUserAttribute(attrName, attrValue, realm); } @Override diff --git a/model/api/src/main/java/org/keycloak/models/UserProvider.java b/model/api/src/main/java/org/keycloak/models/UserProvider.java index 1690b7a70c..8712f2bfc4 100755 --- a/model/api/src/main/java/org/keycloak/models/UserProvider.java +++ b/model/api/src/main/java/org/keycloak/models/UserProvider.java @@ -37,7 +37,7 @@ public interface UserProvider extends Provider { List searchForUserByAttributes(Map attributes, RealmModel realm, int firstResult, int maxResults); // Searching by UserModel.attribute (not property) - List searchForUserByUserAttributes(Map attributes, RealmModel realm); + List searchForUserByUserAttribute(String attrName, String attrValue, RealmModel realm); Set getFederatedIdentities(UserModel user, RealmModel realm); FederatedIdentityModel getFederatedIdentity(UserModel user, String socialProvider, RealmModel realm); diff --git a/model/file/src/main/java/org/keycloak/models/file/FileUserProvider.java b/model/file/src/main/java/org/keycloak/models/file/FileUserProvider.java index 0bcc37a8b2..40547a82db 100755 --- a/model/file/src/main/java/org/keycloak/models/file/FileUserProvider.java +++ b/model/file/src/main/java/org/keycloak/models/file/FileUserProvider.java @@ -255,22 +255,18 @@ public class FileUserProvider implements UserProvider { } @Override - public List searchForUserByUserAttributes(Map attributes, RealmModel realm) { + public List searchForUserByUserAttribute(String attrName, String attrValue, RealmModel realm) { Collection users = inMemoryModel.getUsers(realm.getId()); - for (Map.Entry entry : attributes.entrySet()) { - - List matchedUsers = new ArrayList<>(); - for (UserModel user : users) { - List vals = user.getAttribute(entry.getKey()); - if (vals.contains(entry.getValue())) { - matchedUsers.add(user); - } + List matchedUsers = new ArrayList<>(); + for (UserModel user : users) { + List vals = user.getAttribute(attrName); + if (vals.contains(attrValue)) { + matchedUsers.add(user); } - users = matchedUsers; } - return (List) users; + return matchedUsers; } @Override diff --git a/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/DefaultCacheUserProvider.java b/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/DefaultCacheUserProvider.java index a34d70ac45..68b31edb3b 100644 --- a/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/DefaultCacheUserProvider.java +++ b/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/DefaultCacheUserProvider.java @@ -235,8 +235,8 @@ public class DefaultCacheUserProvider implements CacheUserProvider { } @Override - public List searchForUserByUserAttributes(Map attributes, RealmModel realm) { - return getDelegate().searchForUserByUserAttributes(attributes, realm); + public List searchForUserByUserAttribute(String attrName, String attrValue, RealmModel realm) { + return getDelegate().searchForUserByUserAttribute(attrName, attrValue, realm); } @Override diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProvider.java b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProvider.java index 4f02f6c090..d92e93ddea 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProvider.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProvider.java @@ -13,6 +13,7 @@ import org.keycloak.models.UserFederationProviderModel; import org.keycloak.models.UserModel; import org.keycloak.models.UserProvider; import org.keycloak.models.jpa.entities.FederatedIdentityEntity; +import org.keycloak.models.jpa.entities.UserAttributeEntity; import org.keycloak.models.jpa.entities.UserEntity; import org.keycloak.models.utils.CredentialValidation; import org.keycloak.models.utils.KeycloakModelUtils; @@ -400,32 +401,15 @@ public class JpaUserProvider implements UserProvider { } @Override - public List searchForUserByUserAttributes(Map attributes, RealmModel realm) { - StringBuilder builder = new StringBuilder("select attr.user,count(attr.user) from UserAttributeEntity attr where attr.user.realmId = :realmId"); - boolean first = true; - for (Map.Entry entry : attributes.entrySet()) { - String attrName = entry.getKey(); - if (first) { - builder.append(" and "); - first = false; - } else { - builder.append(" or "); - } - builder.append(" ( attr.name like :").append(attrName); - builder.append(" and attr.value like :").append(attrName).append("val )"); - } - builder.append(" group by attr.user having count(attr.user) = " + attributes.size()); - Query query = em.createQuery(builder.toString()); - query.setParameter("realmId", realm.getId()); - for (Map.Entry entry : attributes.entrySet()) { - query.setParameter(entry.getKey(), entry.getKey()); - query.setParameter(entry.getKey() + "val", entry.getValue()); - } - List results = query.getResultList(); + public List searchForUserByUserAttribute(String attrName, String attrValue, RealmModel realm) { + TypedQuery query = em.createNamedQuery("getAttributesByNameAndValue", UserAttributeEntity.class); + query.setParameter("name", attrName); + query.setParameter("value", attrValue); + List results = query.getResultList(); List users = new ArrayList(); - for (Object o : results) { - UserEntity user = (UserEntity) ((Object[])o)[0]; + for (UserAttributeEntity attr : results) { + UserEntity user = attr.getUser(); users.add(new UserAdapter(realm, em, user)); } return users; diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserAttributeEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserAttributeEntity.java index 430c796421..ec0eb8614e 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserAttributeEntity.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserAttributeEntity.java @@ -21,6 +21,7 @@ import java.util.Set; * @version $Revision: 1 $ */ @NamedQueries({ + @NamedQuery(name="getAttributesByNameAndValue", query="select attr from UserAttributeEntity attr where attr.name = :name and attr.value = :value"), @NamedQuery(name="deleteUserAttributesByRealm", query="delete from UserAttributeEntity attr where attr.user IN (select u from UserEntity u where u.realmId=:realmId)"), @NamedQuery(name="deleteUserAttributesByRealmAndLink", query="delete from UserAttributeEntity attr where attr.user IN (select u from UserEntity u where u.realmId=:realmId and u.federationLink=:link)") }) diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoUserProvider.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoUserProvider.java index a433fead56..308d9fb1d4 100755 --- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoUserProvider.java +++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoUserProvider.java @@ -231,13 +231,10 @@ public class MongoUserProvider implements UserProvider { } @Override - public List searchForUserByUserAttributes(Map attributes, RealmModel realm) { + public List searchForUserByUserAttribute(String attrName, String attrValue, RealmModel realm) { QueryBuilder queryBuilder = new QueryBuilder() .and("realmId").is(realm.getId()); - - for (Map.Entry entry : attributes.entrySet()) { - queryBuilder.and("attributes." + entry.getKey()).is(entry.getValue()); - } + queryBuilder.and("attributes." + attrName).is(attrValue); List users = getMongoStore().loadEntities(MongoUserEntity.class, queryBuilder.get(), invocationContext); return convertUserEntities(realm, users); diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserModelTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserModelTest.java index 8fbfdcec78..258dd3cbd7 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserModelTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserModelTest.java @@ -193,8 +193,8 @@ public class UserModelTest extends AbstractModelTest { Assert.assertEquals("val23", attrVals.get(0)); } - // @Test - public void testSearchByUserAttributes() throws Exception { + @Test + public void testSearchByUserAttribute() throws Exception { RealmModel realm = realmManager.createRealm("original"); UserModel user1 = session.users().addUser(realm, "user1"); UserModel user2 = session.users().addUser(realm, "user2"); @@ -210,20 +210,21 @@ public class UserModelTest extends AbstractModelTest { commit(); - Map attributes = new HashMap(); - attributes.put("key1", "value1"); - List users = session.users().searchForUserByUserAttributes(attributes, realm); + List users = session.users().searchForUserByUserAttribute("key1", "value1", realm); Assert.assertEquals(2, users.size()); Assert.assertTrue(users.contains(user1)); Assert.assertTrue(users.contains(user2)); - attributes.put("key2", "value21"); - users = session.users().searchForUserByUserAttributes(attributes, realm); - Assert.assertEquals(1, users.size()); + users = session.users().searchForUserByUserAttribute("key2", "value21", realm); + Assert.assertEquals(2, users.size()); Assert.assertTrue(users.contains(user1)); + Assert.assertTrue(users.contains(user3)); - attributes.put("key3", "value3"); - users = session.users().searchForUserByUserAttributes(attributes, realm); + users = session.users().searchForUserByUserAttribute("key2", "value22", realm); + Assert.assertEquals(1, users.size()); + Assert.assertTrue(users.contains(user2)); + + users = session.users().searchForUserByUserAttribute("key3", "value3", realm); Assert.assertEquals(0, users.size()); }