From f69497eb28ab6c6595a4a335607d03b0c7ba229d Mon Sep 17 00:00:00 2001 From: Michal Hajas Date: Fri, 26 Aug 2022 13:09:41 +0200 Subject: [PATCH] KEYCLOAK-12988 Deprecate getUsers* methods in favor of searchUsers* variants Closes #14018 --- .../cache/infinispan/UserCacheSession.java | 21 +------- .../keycloak/models/jpa/JpaUserProvider.java | 35 +++++-------- .../models/jpa/entities/UserEntity.java | 2 - .../migration/migrators/MigrateTo1_4_0.java | 8 ++- .../keycloak/storage/UserStorageManager.java | 25 --------- .../util/MultipleStepsExportProvider.java | 3 +- .../models/map/user/MapUserProvider.java | 33 +++--------- .../org/keycloak/models/UserProvider.java | 52 +++++++++---------- .../storage/user/UserQueryProvider.java | 51 ++++++++---------- .../exportimport/util/ExportUtils.java | 3 +- .../admin/IdentityProviderResource.java | 4 +- .../resources/admin/UsersResource.java | 2 +- .../org/keycloak/testsuite/ProfileAssume.java | 2 +- .../federation/ldap/LDAPSyncTest.java | 6 ++- .../storage/UserStorageFailureTest.java | 3 +- .../testsuite/model/UserModelTest.java | 4 +- .../testsuite/util/cli/TestCacheUtils.java | 4 +- 17 files changed, 98 insertions(+), 160 deletions(-) diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/UserCacheSession.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/UserCacheSession.java index f632e2acc3..f7b748947f 100755 --- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/UserCacheSession.java +++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/UserCacheSession.java @@ -544,15 +544,11 @@ public class UserCacheSession implements UserCache.Streams, OnCreateComponent, O } } - @Override - public Stream getUsersStream(RealmModel realm, boolean includeServiceAccounts) { - return getDelegate().getUsersStream(realm, includeServiceAccounts); - } - @Override public CredentialValidationOutput getUserByCredential(RealmModel realm, CredentialInput input) { return getDelegate().getUserByCredential(realm, input); } + @Override public int getUsersCount(RealmModel realm, boolean includeServiceAccount) { return getDelegate().getUsersCount(realm, includeServiceAccount); @@ -583,21 +579,6 @@ public class UserCacheSession implements UserCache.Streams, OnCreateComponent, O return getDelegate().getUsersCount(realm, params, groupIds); } - @Override - public Stream getUsersStream(RealmModel realm, Integer firstResult, Integer maxResults, boolean includeServiceAccounts) { - return getDelegate().getUsersStream(realm, firstResult, maxResults, includeServiceAccounts); - } - - @Override - public Stream getUsersStream(RealmModel realm) { - return getUsersStream(realm, false); - } - - @Override - public Stream getUsersStream(RealmModel realm, Integer firstResult, Integer maxResults) { - return getUsersStream(realm, firstResult, maxResults, false); - } - @Override public Stream searchForUserStream(RealmModel realm, String search) { return getDelegate().searchForUserStream(realm, search); 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 7455fabe43..f604d84f4d 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 @@ -68,6 +68,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.stream.Stream; @@ -748,21 +749,6 @@ public class JpaUserProvider implements UserProvider.Streams, UserCredentialStor return result.intValue(); } - @Override - public Stream getUsersStream(RealmModel realm, Integer firstResult, Integer maxResults) { - return getUsersStream(realm, firstResult, maxResults, false); - } - - @Override - public Stream getUsersStream(RealmModel realm, Integer firstResult, Integer maxResults, boolean includeServiceAccounts) { - String queryName = includeServiceAccounts ? "getAllUsersByRealm" : "getAllUsersByRealmExcludeServiceAccount" ; - - TypedQuery query = em.createNamedQuery(queryName, UserEntity.class); - query.setParameter("realmId", realm.getId()); - - return closing(paginateQuery(query, firstResult, maxResults).getResultStream().map(entity -> new UserAdapter(session, realm, em, entity))); - } - @Override public Stream getGroupMembersStream(RealmModel realm, GroupModel group, Integer firstResult, Integer maxResults) { TypedQuery query = em.createNamedQuery("groupMembership", UserEntity.class); @@ -781,9 +767,10 @@ public class JpaUserProvider implements UserProvider.Streams, UserCredentialStor @Override public Stream searchForUserStream(RealmModel realm, String search, Integer firstResult, Integer maxResults) { - Map attributes = new HashMap<>(); + Map attributes = new HashMap<>(2); attributes.put(UserModel.SEARCH, search); - session.setAttribute(UserModel.INCLUDE_SERVICE_ACCOUNT, false); + attributes.put(UserModel.INCLUDE_SERVICE_ACCOUNT, Boolean.FALSE.toString()); + return searchForUserStream(realm, attributes, firstResult, maxResults); } @@ -798,10 +785,6 @@ public class JpaUserProvider implements UserProvider.Streams, UserCredentialStor predicates.add(builder.equal(root.get("realmId"), realm.getId())); - if (!session.getAttributeOrDefault(UserModel.INCLUDE_SERVICE_ACCOUNT, true)) { - predicates.add(root.get("serviceAccountClientLink").isNull()); - } - Join federatedIdentitiesJoin = null; for (Map.Entry entry : attributes.entrySet()) { @@ -863,6 +846,13 @@ public class JpaUserProvider implements UserProvider.Streams, UserCredentialStor builder.equal(builder.lower(attributesJoin.get("value")), value.toLowerCase()))); break; + case UserModel.INCLUDE_SERVICE_ACCOUNT: { + if (!attributes.containsKey(UserModel.INCLUDE_SERVICE_ACCOUNT) + || !Boolean.parseBoolean(attributes.get(UserModel.INCLUDE_SERVICE_ACCOUNT))) { + predicates.add(root.get("serviceAccountClientLink").isNull()); + } + break; + } } } @@ -908,7 +898,8 @@ public class JpaUserProvider implements UserProvider.Streams, UserCredentialStor UserProvider users = session.users(); return closing(paginateQuery(query, firstResult, maxResults).getResultStream()) - .map(userEntity -> users.getUserById(realm, userEntity.getId())); + .map(userEntity -> users.getUserById(realm, userEntity.getId())) + .filter(Objects::nonNull); } @Override diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserEntity.java index f54d9ac2bb..e5cbcc5c00 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserEntity.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserEntity.java @@ -42,8 +42,6 @@ import java.util.LinkedList; * @version $Revision: 1 $ */ @NamedQueries({ - @NamedQuery(name="getAllUsersByRealm", query="select u from UserEntity u where u.realmId = :realmId order by u.username"), - @NamedQuery(name="getAllUsersByRealmExcludeServiceAccount", query="select u from UserEntity u where u.realmId = :realmId and (u.serviceAccountClientLink is null) order by u.username"), @NamedQuery(name="getRealmUserByUsername", query="select u from UserEntity u where u.username = :username and u.realmId = :realmId"), @NamedQuery(name="getRealmUserByEmail", query="select u from UserEntity u where u.email = :email and u.realmId = :realmId"), @NamedQuery(name="getRealmUserByLastName", query="select u from UserEntity u where u.lastName = :lastName and u.realmId = :realmId"), diff --git a/model/legacy-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_4_0.java b/model/legacy-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_4_0.java index b80fd6dd9c..8734b202a3 100755 --- a/model/legacy-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_4_0.java +++ b/model/legacy-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_4_0.java @@ -24,6 +24,7 @@ import org.keycloak.models.KeycloakSession; import org.keycloak.models.LDAPConstants; import org.keycloak.models.LegacyRealmModel; import org.keycloak.models.RealmModel; +import org.keycloak.models.UserModel; import org.keycloak.models.cache.UserCache; import org.keycloak.models.utils.DefaultAuthenticationFlows; import org.keycloak.models.utils.DefaultRequiredActions; @@ -33,7 +34,9 @@ import org.keycloak.storage.UserStoragePrivateUtil; import org.keycloak.storage.UserStorageUtil; import java.util.Arrays; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Objects; /** @@ -81,7 +84,10 @@ public class MigrateTo1_4_0 implements Migration { } private void migrateUsers(KeycloakSession session, RealmModel realm) { - UserStoragePrivateUtil.userLocalStorage(session).getUsersStream(realm, false) + Map searchAttributes = new HashMap<>(1); + searchAttributes.put(UserModel.INCLUDE_SERVICE_ACCOUNT, Boolean.FALSE.toString()); + + UserStoragePrivateUtil.userLocalStorage(session).searchForUserStream(realm, searchAttributes) .forEach(user -> { String email = KeycloakModelUtils.toLowerCaseSafe(user.getEmail()); if (email != null && !email.equals(user.getEmail())) { diff --git a/model/legacy-private/src/main/java/org/keycloak/storage/UserStorageManager.java b/model/legacy-private/src/main/java/org/keycloak/storage/UserStorageManager.java index 487fe904de..9132f9238e 100755 --- a/model/legacy-private/src/main/java/org/keycloak/storage/UserStorageManager.java +++ b/model/legacy-private/src/main/java/org/keycloak/storage/UserStorageManager.java @@ -379,31 +379,6 @@ public class UserStorageManager extends AbstractStorageManager getUsersStream(RealmModel realm) { - return getUsersStream(realm, null, null, false); - } - - @Override - public Stream getUsersStream(RealmModel realm, Integer firstResult, Integer maxResults) { - return getUsersStream(realm, firstResult, maxResults, false); - } - - @Override - public Stream getUsersStream(final RealmModel realm, Integer firstResult, Integer maxResults, final boolean includeServiceAccounts) { - Stream results = query((provider, firstResultInQuery, maxResultsInQuery) -> { - if (provider instanceof UserProvider) { // it is local storage - return ((UserProvider) provider).getUsersStream(realm, firstResultInQuery, maxResultsInQuery, includeServiceAccounts); - } else if (provider instanceof UserQueryProvider) { - return ((UserQueryProvider)provider).getUsersStream(realm); - } - return Stream.empty(); - } - , realm, firstResult, maxResults); - return importValidation(realm, results); - } - @Override public int getUsersCount(RealmModel realm, boolean includeServiceAccount) { int localStorageUsersCount = localStorage().getUsersCount(realm, includeServiceAccount); diff --git a/model/legacy-services/src/main/java/org/keycloak/exportimport/util/MultipleStepsExportProvider.java b/model/legacy-services/src/main/java/org/keycloak/exportimport/util/MultipleStepsExportProvider.java index 4d25ba1cde..1a5e0d6453 100755 --- a/model/legacy-services/src/main/java/org/keycloak/exportimport/util/MultipleStepsExportProvider.java +++ b/model/legacy-services/src/main/java/org/keycloak/exportimport/util/MultipleStepsExportProvider.java @@ -31,6 +31,7 @@ import org.keycloak.representations.idm.RealmRepresentation; import org.keycloak.storage.UserStorageUtil; import java.io.IOException; +import java.util.Collections; import java.util.List; import java.util.stream.Collectors; @@ -114,7 +115,7 @@ public abstract class MultipleStepsExportProvider implements ExportProvider { protected void runExportImportTask(KeycloakSession session) throws IOException { RealmModel realm = session.realms().getRealmByName(realmName); usersHolder.users = session.users() - .getUsersStream(realm, usersHolder.currentPageStart, usersHolder.currentPageEnd - usersHolder.currentPageStart, true) + .searchForUserStream(realm, Collections.emptyMap(), usersHolder.currentPageStart, usersHolder.currentPageEnd - usersHolder.currentPageStart) .collect(Collectors.toList()); writeUsers(realmName + "-users-" + (usersHolder.currentPageStart / countPerPage) + ".json", session, realm, usersHolder.users); diff --git a/model/map/src/main/java/org/keycloak/models/map/user/MapUserProvider.java b/model/map/src/main/java/org/keycloak/models/map/user/MapUserProvider.java index ee07723f33..0f5d35d4e1 100644 --- a/model/map/src/main/java/org/keycloak/models/map/user/MapUserProvider.java +++ b/model/map/src/main/java/org/keycloak/models/map/user/MapUserProvider.java @@ -540,32 +540,12 @@ public class MapUserProvider implements UserProvider.Streams { return (int) tx.getCount(withCriteria(mcb)); } - @Override - public Stream getUsersStream(RealmModel realm, Integer firstResult, Integer maxResults, boolean includeServiceAccounts) { - LOG.tracef("getUsersStream(%s, %d, %d, %s)%s", realm, firstResult, maxResults, includeServiceAccounts, getShortStackTrace()); - DefaultModelCriteria mcb = criteria(); - mcb = mcb.compare(SearchableFields.REALM_ID, Operator.EQ, realm.getId()); - - if (! includeServiceAccounts) { - mcb = mcb.compare(SearchableFields.SERVICE_ACCOUNT_CLIENT, Operator.NOT_EXISTS); - } - - return tx.read(withCriteria(mcb).pagination(firstResult, maxResults, SearchableFields.USERNAME)) - .map(entityToAdapterFunc(realm)); - } - - @Override - public Stream getUsersStream(RealmModel realm, Integer firstResult, Integer maxResults) { - LOG.tracef("getUsersStream(%s, %d, %d)%s", realm, firstResult, maxResults, getShortStackTrace()); - return getUsersStream(realm, firstResult, maxResults, false); - } - @Override public Stream searchForUserStream(RealmModel realm, String search, Integer firstResult, Integer maxResults) { LOG.tracef("searchForUserStream(%s, %s, %d, %d)%s", realm, search, firstResult, maxResults, getShortStackTrace()); Map attributes = new HashMap<>(); attributes.put(UserModel.SEARCH, search); - session.setAttribute(UserModel.INCLUDE_SERVICE_ACCOUNT, false); + attributes.put(UserModel.INCLUDE_SERVICE_ACCOUNT, Boolean.FALSE.toString()); return searchForUserStream(realm, attributes, firstResult, maxResults); } @@ -576,10 +556,6 @@ public class MapUserProvider implements UserProvider.Streams { final DefaultModelCriteria mcb = criteria(); DefaultModelCriteria criteria = mcb.compare(SearchableFields.REALM_ID, Operator.EQ, realm.getId()); - if (! session.getAttributeOrDefault(UserModel.INCLUDE_SERVICE_ACCOUNT, true)) { - criteria = criteria.compare(SearchableFields.SERVICE_ACCOUNT_CLIENT, Operator.NOT_EXISTS); - } - final boolean exactSearch = Boolean.parseBoolean(attributes.getOrDefault(UserModel.EXACT, Boolean.FALSE.toString())); for (Map.Entry entry : attributes.entrySet()) { @@ -638,6 +614,13 @@ public class MapUserProvider implements UserProvider.Streams { value); break; } + case UserModel.INCLUDE_SERVICE_ACCOUNT: { + if (!attributes.containsKey(UserModel.INCLUDE_SERVICE_ACCOUNT) + || !Boolean.parseBoolean(attributes.get(UserModel.INCLUDE_SERVICE_ACCOUNT))) { + criteria = criteria.compare(SearchableFields.SERVICE_ACCOUNT_CLIENT, Operator.NOT_EXISTS); + } + break; + } case UserModel.EXACT: break; default: diff --git a/server-spi/src/main/java/org/keycloak/models/UserProvider.java b/server-spi/src/main/java/org/keycloak/models/UserProvider.java index 2df2cc71bd..cc864dade9 100755 --- a/server-spi/src/main/java/org/keycloak/models/UserProvider.java +++ b/server-spi/src/main/java/org/keycloak/models/UserProvider.java @@ -24,7 +24,9 @@ import org.keycloak.storage.user.UserLookupProvider; import org.keycloak.storage.user.UserQueryProvider; import org.keycloak.storage.user.UserRegistrationProvider; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -71,10 +73,13 @@ public interface UserProvider extends Provider, UserModel getServiceAccount(ClientModel client); /** - * @deprecated Use {@link #getUsersStream(RealmModel, boolean) getUsersStream} instead. + * @deprecated Use {@link UserQueryProvider#searchForUserStream(RealmModel, Map)} with + * {@link UserModel#INCLUDE_SERVICE_ACCOUNT} within params instead. */ @Deprecated - List getUsers(RealmModel realm, boolean includeServiceAccounts); + default List getUsers(RealmModel realm, boolean includeServiceAccounts) { + return this.getUsersStream(realm, includeServiceAccounts).collect(Collectors.toList()); + } /** * Obtains the users associated with the specified realm. @@ -82,17 +87,25 @@ public interface UserProvider extends Provider, * @param realm a reference to the realm being used for the search. * @param includeServiceAccounts {@code true} if service accounts should be included in the result; {@code false} otherwise. * @return a non-null {@link Stream} of users associated withe the realm. + * + * @deprecated Use {@link UserQueryProvider#searchForUserStream(RealmModel, Map)} with + * {@link UserModel#INCLUDE_SERVICE_ACCOUNT} within params instead. */ + @Deprecated default Stream getUsersStream(RealmModel realm, boolean includeServiceAccounts) { - List value = this.getUsers(realm, includeServiceAccounts); - return value != null ? value.stream() : Stream.empty(); + Map searchAttributes = new HashMap<>(1); + searchAttributes.put(UserModel.INCLUDE_SERVICE_ACCOUNT, Boolean.toString(includeServiceAccounts)); + return this.searchForUserStream(realm, searchAttributes); } /** - * @deprecated Use {@link #getUsersStream(RealmModel, Integer, Integer, boolean) getUsersStream} instead. + * @deprecated Use {@link UserQueryProvider#searchForUserStream(RealmModel, Map, Integer, Integer)} with + * {@link UserModel#INCLUDE_SERVICE_ACCOUNT} within params instead. */ @Deprecated - List getUsers(RealmModel realm, int firstResult, int maxResults, boolean includeServiceAccounts); + default List getUsers(RealmModel realm, int firstResult, int maxResults, boolean includeServiceAccounts) { + return this.getUsersStream(realm, firstResult, maxResults, includeServiceAccounts).collect(Collectors.toList()); + } /** * Obtains the users associated with the specified realm. @@ -102,10 +115,15 @@ public interface UserProvider extends Provider, * @param maxResults maximum number of results to return. Ignored if negative or {@code null}. * @param includeServiceAccounts {@code true} if service accounts should be included in the result; {@code false} otherwise. * @return a non-null {@link Stream} of users associated withe the realm. + * + * @deprecated Use {@link UserQueryProvider#searchForUserStream(RealmModel, Map, Integer, Integer)} + * with {@link UserModel#INCLUDE_SERVICE_ACCOUNT} within params */ + @Deprecated default Stream getUsersStream(RealmModel realm, Integer firstResult, Integer maxResults, boolean includeServiceAccounts) { - List value = this.getUsers(realm, firstResult == null ? -1 : firstResult, maxResults == null ? -1 : maxResults, includeServiceAccounts); - return value != null ? value.stream() : Stream.empty(); + Map searchAttributes = new HashMap<>(1); + searchAttributes.put(UserModel.INCLUDE_SERVICE_ACCOUNT, Boolean.toString(includeServiceAccounts)); + return this.searchForUserStream(realm, searchAttributes, firstResult, maxResults); } /** @@ -412,23 +430,5 @@ public interface UserProvider extends Provider, @Override Stream getConsentsStream(RealmModel realm, String userId); - - @Override - default List getUsers(RealmModel realm, boolean includeServiceAccounts) { - return this.getUsersStream(realm, includeServiceAccounts).collect(Collectors.toList()); - } - - @Override - default Stream getUsersStream(RealmModel realm, boolean includeServiceAccounts) { - return getUsersStream(realm, null, null, includeServiceAccounts); - } - - @Override - default List getUsers(RealmModel realm, int firstResult, int maxResults, boolean includeServiceAccounts) { - return this.getUsersStream(realm, firstResult, maxResults, includeServiceAccounts).collect(Collectors.toList()); - } - - @Override - Stream getUsersStream(RealmModel realm, Integer firstResult, Integer maxResults, boolean includeServiceAccounts); } } diff --git a/server-spi/src/main/java/org/keycloak/storage/user/UserQueryProvider.java b/server-spi/src/main/java/org/keycloak/storage/user/UserQueryProvider.java index e31d8b509e..7f4bf99d33 100644 --- a/server-spi/src/main/java/org/keycloak/storage/user/UserQueryProvider.java +++ b/server-spi/src/main/java/org/keycloak/storage/user/UserQueryProvider.java @@ -64,7 +64,7 @@ public interface UserQueryProvider { if (groupIds == null || groupIds.isEmpty()) { return 0; } - return countUsersInGroups(getUsersStream(realm), groupIds); + return countUsersInGroups(searchForUserStream(realm, Collections.emptyMap()), groupIds); } /** @@ -176,26 +176,31 @@ public interface UserQueryProvider { } /** - * @deprecated Use {@link #getUsersStream(RealmModel) getUsersStream} instead. + * @deprecated Use {@link #searchForUserStream(RealmModel, Map)} with an empty params map instead. */ @Deprecated - List getUsers(RealmModel realm); + default List getUsers(RealmModel realm) { + return searchForUserStream(realm, Collections.emptyMap()).collect(Collectors.toList()); + } /** * Searches all users in the realm. * * @param realm a reference to the realm. * @return a non-null {@link Stream} of users. + * @deprecated Use {@link #searchForUserStream(RealmModel, Map)} with an empty params map instead. */ + @Deprecated default Stream getUsersStream(RealmModel realm) { - List value = this.getUsers(realm); - return value != null ? value.stream() : Stream.empty(); + return searchForUserStream(realm, Collections.emptyMap()); } /** - * @deprecated Use {@link #getUsersStream(RealmModel, Integer, Integer) getUsersStream} instead. + * @deprecated Use {@link #searchForUserStream(RealmModel, Map, Integer, Integer)} with an empty params map instead. */ @Deprecated - List getUsers(RealmModel realm, int firstResult, int maxResults); + default List getUsers(RealmModel realm, int firstResult, int maxResults) { + return searchForUserStream(realm, Collections.emptyMap(), firstResult, maxResults).collect(Collectors.toList()); + } /** * Searches all users in the realm, starting from the {@code firstResult} and containing at most {@code maxResults}. @@ -204,11 +209,11 @@ public interface UserQueryProvider { * @param firstResult first result to return. Ignored if negative or {@code null}. * @param maxResults maximum number of results to return. Ignored if negative or {@code null}. * @return a non-null {@link Stream} of users. + * @deprecated Use {@link #searchForUserStream(RealmModel, Map, Integer, Integer)} with an empty params map instead. */ + @Deprecated default Stream getUsersStream(RealmModel realm, Integer firstResult, Integer maxResults) { - List value = this.getUsers(realm, firstResult == null ? -1 : firstResult, - maxResults == null ? -1 : maxResults); - return value != null ? value.stream() : Stream.empty(); + return searchForUserStream(realm, Collections.emptyMap(), firstResult, maxResults); } /** @@ -295,6 +300,14 @@ public interface UserQueryProvider { * from idp with the given alias configured (case sensitive string) *
  • {@link UserModel#IDP_USER_ID} - search for users with federated identity with * the given userId (case sensitive string)
  • + *
  • {@link UserModel#SEARCH} - Searches for users whose username, email, first name or last name contain any + * of the strings in {@code search} separated by whitespace. If possible, implementations should treat the + * parameter values as partial match patterns (i.e. in RDMBS terms use LIKE).
  • + *
  • {@link UserModel#EXACT} - Used alongside with {@link UserModel#FIRST_NAME}, {@link UserModel#LAST_NAME}, + * {@link UserModel#EMAIL} and {@link UserModel#USERNAME} parameters; if true searching is done using equals + * otherwise partial match should be enough to fulfill these parameters
  • + *
  • {@link UserModel#INCLUDE_SERVICE_ACCOUNT} - When false, users that have a service account link are not + * included in result
  • * * * If possible, implementations should treat the parameter values as partial match patterns i.e. in RDMBS terms use LIKE. @@ -593,24 +606,6 @@ public interface UserQueryProvider { return getUsersCount(realm, params, groupIds); } - @Override - default List getUsers(RealmModel realm) { - return this.getUsersStream(realm).collect(Collectors.toList()); - } - - @Override - default Stream getUsersStream(RealmModel realm) { - return getUsersStream(realm, null, null); - } - - @Override - default List getUsers(RealmModel realm, int firstResult, int maxResults) { - return this.getUsersStream(realm, firstResult, maxResults).collect(Collectors.toList()); - } - - @Override - Stream getUsersStream(RealmModel realm, Integer firstResult, Integer maxResults); - @Override default List searchForUser(String search, RealmModel realm) { return this.searchForUserStream(realm, search).collect(Collectors.toList()); diff --git a/services/src/main/java/org/keycloak/exportimport/util/ExportUtils.java b/services/src/main/java/org/keycloak/exportimport/util/ExportUtils.java index 01aa479b4c..54d6081310 100755 --- a/services/src/main/java/org/keycloak/exportimport/util/ExportUtils.java +++ b/services/src/main/java/org/keycloak/exportimport/util/ExportUtils.java @@ -65,6 +65,7 @@ import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; @@ -227,7 +228,7 @@ public class ExportUtils { // Finally users if needed if (options.isUsersIncluded()) { - List users = session.users().getUsersStream(realm, true) + List users = session.users().searchForUserStream(realm, Collections.emptyMap()) .map(user -> exportUser(session, realm, user, options, internal)) .collect(Collectors.toList()); diff --git a/services/src/main/java/org/keycloak/services/resources/admin/IdentityProviderResource.java b/services/src/main/java/org/keycloak/services/resources/admin/IdentityProviderResource.java index a0c3d1ea53..3ccbd0b9db 100644 --- a/services/src/main/java/org/keycloak/services/resources/admin/IdentityProviderResource.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/IdentityProviderResource.java @@ -61,6 +61,8 @@ import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; import java.util.Map; import java.util.Objects; import java.util.function.Function; @@ -191,7 +193,7 @@ public class IdentityProviderResource { // Admin changed the ID (alias) of identity provider. We must update all clients and users logger.debug("Changing providerId in all clients and linked users. oldProviderId=" + oldProviderId + ", newProviderId=" + newProviderId); - updateUsersAfterProviderAliasChange(session.users().getUsersStream(realm, false), + updateUsersAfterProviderAliasChange(session.users().searchForUserStream(realm, Collections.singletonMap(UserModel.INCLUDE_SERVICE_ACCOUNT, Boolean.FALSE.toString())), oldProviderId, newProviderId, realm, session); } } diff --git a/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java b/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java index 8425e62482..3750401005 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java @@ -433,7 +433,7 @@ public class UsersResource { } private Stream searchForUser(Map attributes, RealmModel realm, UserPermissionEvaluator usersEvaluator, Boolean briefRepresentation, Integer firstResult, Integer maxResults, Boolean includeServiceAccounts) { - session.setAttribute(UserModel.INCLUDE_SERVICE_ACCOUNT, includeServiceAccounts); + attributes.put(UserModel.INCLUDE_SERVICE_ACCOUNT, includeServiceAccounts.toString()); if (!auth.users().canView()) { Set groupModels = auth.groups().getGroupsWithViewPermission(); diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/ProfileAssume.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/ProfileAssume.java index 09d11b5b09..5aad6bd10b 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/ProfileAssume.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/ProfileAssume.java @@ -58,7 +58,7 @@ public class ProfileAssume { } public static void assumeFeatureDisabled(Profile.Feature feature) { - Assume.assumeTrue("Ignoring test as feature " + feature.name() + " is disabled", !isFeatureEnabled(feature)); + Assume.assumeTrue("Ignoring test as feature " + feature.name() + " is enabled", !isFeatureEnabled(feature)); } public static void assumePreview() { diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/ldap/LDAPSyncTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/ldap/LDAPSyncTest.java index d0b869e1b2..f1ad720ac9 100755 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/ldap/LDAPSyncTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/ldap/LDAPSyncTest.java @@ -307,7 +307,8 @@ public class LDAPSyncTest extends AbstractLDAPTest { LDAPTestContext ctx = LDAPTestContext.init(session); // Remove all users from model - UserStoragePrivateUtil.userLocalStorage(session).getUsersStream(ctx.getRealm(), true) + UserStoragePrivateUtil.userLocalStorage(session) + .searchForUserStream(ctx.getRealm(), Collections.emptyMap()) .collect(Collectors.toList()) .forEach(user -> UserStoragePrivateUtil.userLocalStorage(session).removeUser(ctx.getRealm(), user)); @@ -356,7 +357,8 @@ public class LDAPSyncTest extends AbstractLDAPTest { LDAPTestContext ctx = LDAPTestContext.init(session); // Remove all users from model - UserStoragePrivateUtil.userLocalStorage(session).getUsersStream(ctx.getRealm(), true) + UserStoragePrivateUtil.userLocalStorage(session) + .searchForUserStream(ctx.getRealm(), Collections.emptyMap()) .peek(user -> System.out.println("trying to delete user: " + user.getUsername())) .collect(Collectors.toList()) .forEach(user -> { diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/storage/UserStorageFailureTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/storage/UserStorageFailureTest.java index a7e3e081c4..837aab3036 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/storage/UserStorageFailureTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/storage/UserStorageFailureTest.java @@ -56,6 +56,7 @@ import org.keycloak.testsuite.pages.AppPage; import org.keycloak.testsuite.pages.LoginPage; import org.keycloak.testsuite.util.OAuthClient; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -345,7 +346,7 @@ public class UserStorageFailureTest extends AbstractTestRealmKeycloakTest { Assert.assertEquals(1, result.count()); // we run a terminal operation on the stream to make sure it is consumed. - session.users().getUsersStream(realm).count(); + session.users().searchForUserStream(realm, Collections.emptyMap()).count(); session.users().getUsersCount(realm); UserModel user = session.users().getUserByUsername(realm, FailableHardcodedStorageProvider.username); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/model/UserModelTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/model/UserModelTest.java index 7039eae89f..487ae5ef22 100755 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/model/UserModelTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/model/UserModelTest.java @@ -479,11 +479,11 @@ public class UserModelTest extends AbstractTestRealmKeycloakTest { Assert.assertThat(users, hasSize(1)); Assert.assertThat(users, contains(user2)); - users = currentSession.users().getUsersStream(realm, false).collect(Collectors.toList()); + users = currentSession.users().searchForUserStream(realm, Collections.singletonMap(UserModel.INCLUDE_SERVICE_ACCOUNT, Boolean.FALSE.toString())).collect(Collectors.toList()); Assert.assertThat(users, hasSize(1)); Assert.assertThat(users, contains(user2)); - users = currentSession.users().getUsersStream(realm, true).collect(Collectors.toList()); + users = currentSession.users().searchForUserStream(realm, Collections.emptyMap()).collect(Collectors.toList()); Assert.assertThat(users, hasSize(2)); Assert.assertThat(users, containsInAnyOrder(user1, user2)); diff --git a/testsuite/utils/src/main/java/org/keycloak/testsuite/util/cli/TestCacheUtils.java b/testsuite/utils/src/main/java/org/keycloak/testsuite/util/cli/TestCacheUtils.java index c01b68e875..6e10827cd5 100644 --- a/testsuite/utils/src/main/java/org/keycloak/testsuite/util/cli/TestCacheUtils.java +++ b/testsuite/utils/src/main/java/org/keycloak/testsuite/util/cli/TestCacheUtils.java @@ -24,6 +24,8 @@ import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; import org.keycloak.models.RoleContainerModel; +import java.util.Collections; + /** * @author Marek Posolda */ @@ -45,7 +47,7 @@ public class TestCacheUtils { realm.getClientScopesStream().map(ClientScopeModel::getId).forEach(realm::getClientScopeById); - session.users().getUsersStream(realm).forEach(user -> { + session.users().searchForUserStream(realm, Collections.emptyMap()).forEach(user -> { session.users().getUserById(realm, user.getId()); if (user.getEmail() != null) { session.users().getUserByEmail(realm, user.getEmail());