diff --git a/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPIdentityStoreRegistry.java b/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPIdentityStoreRegistry.java index bb00804c6b..d224940605 100644 --- a/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPIdentityStoreRegistry.java +++ b/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPIdentityStoreRegistry.java @@ -25,10 +25,8 @@ import org.keycloak.models.RealmModel; import org.keycloak.storage.ldap.idm.store.ldap.LDAPIdentityStore; import org.keycloak.storage.ldap.mappers.LDAPConfigDecorator; -import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -import java.util.stream.Collectors; /** * @author Marek Posolda @@ -68,12 +66,9 @@ public class LDAPIdentityStoreRegistry { if (logger.isDebugEnabled()) { RealmModel realm = session.realms().getRealm(ldapModel.getParentId()); - List mappers = realm.getComponents(ldapModel.getId()); - mappers.stream().forEach((ComponentModel c) -> { - - logger.debugf("Mapper for provider: %s, Mapper name: %s, Provider: %s, Mapper configuration: %s", ldapModel.getName(), c.getName(), c.getProviderId(), c.getConfig().toString()); - - }); + realm.getComponentsStream(ldapModel.getId()).forEach(c -> + logger.debugf("Mapper for provider: %s, Mapper name: %s, Provider: %s, Mapper configuration: %s", + ldapModel.getName(), c.getName(), c.getProviderId(), c.getConfig().toString())); } } diff --git a/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPStorageProvider.java b/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPStorageProvider.java index d50a36d895..0224b0a841 100755 --- a/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPStorageProvider.java +++ b/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPStorageProvider.java @@ -25,6 +25,8 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.atomic.AtomicReference; +import java.util.stream.Collectors; import javax.naming.AuthenticationException; @@ -37,7 +39,18 @@ import org.keycloak.credential.CredentialInputUpdater; import org.keycloak.credential.CredentialInputValidator; import org.keycloak.federation.kerberos.impl.KerberosUsernamePasswordAuthenticator; import org.keycloak.federation.kerberos.impl.SPNEGOAuthenticator; -import org.keycloak.models.*; +import org.keycloak.models.CredentialValidationOutput; +import org.keycloak.models.GroupModel; +import org.keycloak.models.KeycloakSession; +import org.keycloak.models.LDAPConstants; +import org.keycloak.models.ModelDuplicateException; +import org.keycloak.models.ModelException; +import org.keycloak.models.RealmModel; +import org.keycloak.models.RequiredActionProviderModel; +import org.keycloak.models.RoleModel; +import org.keycloak.models.UserCredentialModel; +import org.keycloak.models.UserManager; +import org.keycloak.models.UserModel; import org.keycloak.models.cache.CachedUserModel; import org.keycloak.models.credential.PasswordCredentialModel; import org.keycloak.models.utils.DefaultRoles; @@ -58,10 +71,11 @@ import org.keycloak.storage.ldap.idm.query.internal.LDAPQuery; import org.keycloak.storage.ldap.idm.query.internal.LDAPQueryConditionsBuilder; import org.keycloak.storage.ldap.idm.store.ldap.LDAPIdentityStore; import org.keycloak.storage.ldap.kerberos.LDAPProviderKerberosConfig; +import org.keycloak.storage.ldap.mappers.LDAPMappersComparator; +import org.keycloak.storage.ldap.mappers.LDAPOperationDecorator; import org.keycloak.storage.ldap.mappers.LDAPStorageMapper; import org.keycloak.storage.ldap.mappers.LDAPStorageMapperManager; import org.keycloak.storage.ldap.mappers.PasswordUpdateCallback; -import org.keycloak.storage.ldap.mappers.LDAPOperationDecorator; import org.keycloak.storage.user.ImportedUserValidation; import org.keycloak.storage.user.UserLookupProvider; import org.keycloak.storage.user.UserQueryProvider; @@ -91,6 +105,7 @@ public class LDAPStorageProvider implements UserStorageProvider, protected PasswordUpdateCallback updater; protected LDAPStorageMapperManager mapperManager; protected LDAPStorageUserManager userManager; + private LDAPMappersComparator ldapMappersComparator; // these exist to make sure that we only hit ldap once per transaction //protected Map noImportSessionCache = new HashMap<>(); @@ -112,6 +127,8 @@ public class LDAPStorageProvider implements UserStorageProvider, if (kerberosConfig.isAllowKerberosAuthentication()) { supportedCredentialTypes.add(UserCredentialModel.KERBEROS); } + + ldapMappersComparator = new LDAPMappersComparator(getLdapIdentityStore().getConfig()); } public void setUpdater(PasswordUpdateCallback updater) { @@ -192,12 +209,14 @@ public class LDAPStorageProvider implements UserStorageProvider, break; } - List mappers = realm.getComponents(model.getId(), LDAPStorageMapper.class.getName()); - List sortedMappers = mapperManager.sortMappersAsc(mappers); - for (ComponentModel mapperModel : sortedMappers) { - LDAPStorageMapper ldapMapper = mapperManager.getMapper(mapperModel); - proxied = ldapMapper.proxy(ldapObject, proxied, realm); - } + AtomicReference proxy = new AtomicReference<>(proxied); + realm.getComponentsStream(model.getId(), LDAPStorageMapper.class.getName()) + .sorted(ldapMappersComparator.sortAsc()) + .forEachOrdered(mapperModel -> { + LDAPStorageMapper ldapMapper = mapperManager.getMapper(mapperModel); + proxy.set(ldapMapper.proxy(ldapObject, proxy.get(), realm)); + }); + proxied = proxy.get(); if (!model.isImportEnabled()) { proxied = new UpdateOnlyChangeUserModelDelegate(proxied); @@ -241,7 +260,7 @@ public class LDAPStorageProvider implements UserStorageProvider, return Collections.emptyList(); } - List searchResults = new LinkedList(); + List searchResults = new LinkedList<>(); for (LDAPObject ldapUser : ldapObjects) { String ldapUsername = LDAPUtils.getUsername(ldapUser, this.ldapIdentityStore.getConfig()); @@ -286,11 +305,11 @@ public class LDAPStorageProvider implements UserStorageProvider, realm.getDefaultGroupsStream().forEach(proxy::joinGroup); - for (RequiredActionProviderModel r : realm.getRequiredActionProviders()) { - if (r.isEnabled() && r.isDefaultAction()) { - proxy.addRequiredAction(r.getAlias()); - } - } + realm.getRequiredActionProvidersStream() + .filter(RequiredActionProviderModel::isEnabled) + .filter(RequiredActionProviderModel::isDefaultAction) + .map(RequiredActionProviderModel::getAlias) + .forEachOrdered(proxy::addRequiredAction); return proxy; } @@ -397,8 +416,10 @@ public class LDAPStorageProvider implements UserStorageProvider, @Override public List getGroupMembers(RealmModel realm, GroupModel group, int firstResult, int maxResults) { - List mappers = realm.getComponents(model.getId(), LDAPStorageMapper.class.getName()); - List sortedMappers = mapperManager.sortMappersAsc(mappers); + List sortedMappers = realm.getComponentsStream(model.getId(), LDAPStorageMapper.class.getName()) + .sorted(ldapMappersComparator.sortAsc()) + .collect(Collectors.toList()); + for (ComponentModel mapperModel : sortedMappers) { LDAPStorageMapper ldapMapper = mapperManager.getMapper(mapperModel); List users = ldapMapper.getGroupMembers(realm, group, firstResult, maxResults); @@ -418,8 +439,9 @@ public class LDAPStorageProvider implements UserStorageProvider, @Override public List getRoleMembers(RealmModel realm, RoleModel role, int firstResult, int maxResults) { - List mappers = realm.getComponents(model.getId(), LDAPStorageMapper.class.getName()); - List sortedMappers = mapperManager.sortMappersAsc(mappers); + List sortedMappers = realm.getComponentsStream(model.getId(), LDAPStorageMapper.class.getName()) + .sorted(ldapMappersComparator.sortAsc()) + .collect(Collectors.toList()); for (ComponentModel mapperModel : sortedMappers) { LDAPStorageMapper ldapMapper = mapperManager.getMapper(mapperModel); List users = ldapMapper.getRoleMembers(realm, role, firstResult, maxResults); @@ -544,15 +566,16 @@ public class LDAPStorageProvider implements UserStorageProvider, } imported.setEnabled(true); - List mappers = realm.getComponents(model.getId(), LDAPStorageMapper.class.getName()); - List sortedMappers = mapperManager.sortMappersDesc(mappers); - for (ComponentModel mapperModel : sortedMappers) { - if (logger.isTraceEnabled()) { - logger.tracef("Using mapper %s during import user from LDAP", mapperModel); - } - LDAPStorageMapper ldapMapper = mapperManager.getMapper(mapperModel); - ldapMapper.onImportUserFromLDAP(ldapUser, imported, realm, true); - } + UserModel finalImported = imported; + realm.getComponentsStream(model.getId(), LDAPStorageMapper.class.getName()) + .sorted(ldapMappersComparator.sortDesc()) + .forEachOrdered(mapperModel -> { + if (logger.isTraceEnabled()) { + logger.tracef("Using mapper %s during import user from LDAP", mapperModel); + } + LDAPStorageMapper ldapMapper = mapperManager.getMapper(mapperModel); + ldapMapper.onImportUserFromLDAP(ldapUser, finalImported, realm, true); + }); String userDN = ldapUser.getDn().toString(); if (model.isImportEnabled()) imported.setFederationLink(model.getId()); @@ -631,17 +654,17 @@ public class LDAPStorageProvider implements UserStorageProvider, ldapIdentityStore.validatePassword(ldapUser, password); return true; } catch (AuthenticationException ae) { - boolean processed = false; - List mappers = realm.getComponents(model.getId(), LDAPStorageMapper.class.getName()); - List sortedMappers = mapperManager.sortMappersDesc(mappers); - for (ComponentModel mapperModel : sortedMappers) { - if (logger.isTraceEnabled()) { - logger.tracef("Using mapper %s during import user from LDAP", mapperModel); - } - LDAPStorageMapper ldapMapper = mapperManager.getMapper(mapperModel); - processed = processed || ldapMapper.onAuthenticationFailure(ldapUser, user, ae, realm); - } - return processed; + AtomicReference processed = new AtomicReference<>(false); + realm.getComponentsStream(model.getId(), LDAPStorageMapper.class.getName()) + .sorted(ldapMappersComparator.sortDesc()) + .forEachOrdered(mapperModel -> { + if (logger.isTraceEnabled()) { + logger.tracef("Using mapper %s during import user from LDAP", mapperModel); + } + LDAPStorageMapper ldapMapper = mapperManager.getMapper(mapperModel); + processed.set(processed.get() || ldapMapper.onAuthenticationFailure(ldapUser, user, ae, realm)); + }); + return processed.get(); } } } diff --git a/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPStorageProviderFactory.java b/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPStorageProviderFactory.java index db4e5d41a6..66aef7024c 100755 --- a/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPStorageProviderFactory.java +++ b/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPStorageProviderFactory.java @@ -52,8 +52,8 @@ import org.keycloak.storage.ldap.mappers.FullNameLDAPStorageMapperFactory; import org.keycloak.storage.ldap.mappers.HardcodedLDAPAttributeMapper; import org.keycloak.storage.ldap.mappers.HardcodedLDAPAttributeMapperFactory; import org.keycloak.storage.ldap.mappers.LDAPConfigDecorator; +import org.keycloak.storage.ldap.mappers.LDAPMappersComparator; import org.keycloak.storage.ldap.mappers.LDAPStorageMapper; -import org.keycloak.storage.ldap.mappers.LDAPStorageMapperFactory; import org.keycloak.storage.ldap.mappers.UserAttributeLDAPStorageMapper; import org.keycloak.storage.ldap.mappers.UserAttributeLDAPStorageMapperFactory; import org.keycloak.storage.ldap.mappers.msad.MSADUserAccountControlStorageMapperFactory; @@ -62,9 +62,10 @@ import org.keycloak.storage.user.SynchronizationResult; import org.keycloak.utils.CredentialHelper; import java.util.Date; -import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; /** * @author Marek Posolda @@ -241,17 +242,12 @@ public class LDAPStorageProviderFactory implements UserStorageProviderFactory getLDAPConfigDecorators(KeycloakSession session, ComponentModel ldapModel) { RealmModel realm = session.realms().getRealm(ldapModel.getParentId()); - List mapperComponents = realm.getComponents(ldapModel.getId(), LDAPStorageMapper.class.getName()); - - Map result = new HashMap<>(); - for (ComponentModel mapperModel : mapperComponents) { - LDAPStorageMapperFactory mapperFactory = (LDAPStorageMapperFactory) session.getKeycloakSessionFactory().getProviderFactory(LDAPStorageMapper.class, mapperModel.getProviderId()); - if (mapperFactory instanceof LDAPConfigDecorator) { - result.put(mapperModel, (LDAPConfigDecorator) mapperFactory); - } - } - - return result; + return realm.getComponentsStream(ldapModel.getId(), LDAPStorageMapper.class.getName()) + .filter(mapperModel -> session.getKeycloakSessionFactory() + .getProviderFactory(LDAPStorageMapper.class, mapperModel.getProviderId()) instanceof LDAPConfigDecorator) + .collect(Collectors.toMap(Function.identity(), mapperModel -> + (LDAPConfigDecorator) session.getKeycloakSessionFactory() + .getProviderFactory(LDAPStorageMapper.class, mapperModel.getProviderId()))); } @@ -504,14 +500,15 @@ public class LDAPStorageProviderFactory implements UserStorageProviderFactory mappers = realm.getComponents(model.getId(), LDAPStorageMapper.class.getName()); - for (ComponentModel mapperModel : mappers) { - LDAPStorageMapper ldapMapper = session.getProvider(LDAPStorageMapper.class, mapperModel); - SynchronizationResult syncResult = ldapMapper.syncDataFromFederationProviderToKeycloak(realm); - if (syncResult.getAdded() > 0 || syncResult.getUpdated() > 0 || syncResult.getRemoved() > 0 || syncResult.getFailed() > 0) { - logger.infof("Sync of federation mapper '%s' finished. Status: %s", mapperModel.getName(), syncResult.toString()); - } - } + realm.getComponentsStream(model.getId(), LDAPStorageMapper.class.getName()) + .forEach(mapperModel -> { + SynchronizationResult syncResult = session.getProvider(LDAPStorageMapper.class, mapperModel) + .syncDataFromFederationProviderToKeycloak(realm); + if (syncResult.getAdded() > 0 || syncResult.getUpdated() > 0 || syncResult.getRemoved() > 0 + || syncResult.getFailed() > 0) { + logger.infof("Sync of federation mapper '%s' finished. Status: %s", mapperModel.getName(), syncResult.toString()); + } + }); } }); @@ -609,12 +606,14 @@ public class LDAPStorageProviderFactory implements UserStorageProviderFactory federationMappers = currentRealm.getComponents(fedModel.getId(), LDAPStorageMapper.class.getName()); - List sortedMappers = ldapFedProvider.getMapperManager().sortMappersDesc(federationMappers); - for (ComponentModel mapperModel : sortedMappers) { - LDAPStorageMapper ldapMapper = ldapFedProvider.getMapperManager().getMapper(mapperModel); - ldapMapper.onImportUserFromLDAP(ldapUser, currentUser, currentRealm, false); - } + LDAPMappersComparator ldapMappersComparator = new LDAPMappersComparator(ldapFedProvider.getLdapIdentityStore().getConfig()); + currentRealm.getComponentsStream(fedModel.getId(), LDAPStorageMapper.class.getName()) + .sorted(ldapMappersComparator.sortDesc()) + .forEachOrdered(mapperModel -> { + LDAPStorageMapper ldapMapper = ldapFedProvider.getMapperManager().getMapper(mapperModel); + ldapMapper.onImportUserFromLDAP(ldapUser, currentUser, currentRealm, false); + }); + UserCache userCache = session.userCache(); if (userCache != null) { userCache.evict(currentRealm, currentUser); diff --git a/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPUtils.java b/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPUtils.java index 252887f79e..9a1ce30aa6 100755 --- a/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPUtils.java +++ b/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPUtils.java @@ -25,6 +25,7 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.stream.Collectors; import javax.naming.directory.SearchControls; @@ -43,6 +44,7 @@ import org.keycloak.storage.ldap.idm.query.Condition; import org.keycloak.storage.ldap.idm.query.internal.LDAPQuery; import org.keycloak.storage.ldap.idm.query.internal.LDAPQueryConditionsBuilder; import org.keycloak.storage.ldap.idm.store.ldap.LDAPIdentityStore; +import org.keycloak.storage.ldap.mappers.LDAPMappersComparator; import org.keycloak.storage.ldap.mappers.LDAPStorageMapper; import org.keycloak.storage.ldap.mappers.membership.MembershipType; @@ -67,12 +69,13 @@ public class LDAPUtils { ldapUser.setRdnAttributeName(ldapConfig.getRdnLdapAttribute()); ldapUser.setObjectClasses(ldapConfig.getUserObjectClasses()); - List federationMappers = realm.getComponents(ldapProvider.getModel().getId(), LDAPStorageMapper.class.getName()); - List sortedMappers = ldapProvider.getMapperManager().sortMappersAsc(federationMappers); - for (ComponentModel mapperModel : sortedMappers) { - LDAPStorageMapper ldapMapper = ldapProvider.getMapperManager().getMapper(mapperModel); - ldapMapper.onRegisterUserToLDAP(ldapUser, user, realm); - } + LDAPMappersComparator ldapMappersComparator = new LDAPMappersComparator(ldapConfig); + realm.getComponentsStream(ldapProvider.getModel().getId(), LDAPStorageMapper.class.getName()) + .sorted(ldapMappersComparator.sortAsc()) + .forEachOrdered(mapperModel -> { + LDAPStorageMapper ldapMapper = ldapProvider.getMapperManager().getMapper(mapperModel); + ldapMapper.onRegisterUserToLDAP(ldapUser, user, realm); + }); LDAPUtils.computeAndSetDn(ldapConfig, ldapUser); ldapStore.add(ldapUser); @@ -92,7 +95,9 @@ public class LDAPUtils { ldapQuery.addWhereCondition(customFilterCondition); } - List mapperModels = realm.getComponents(ldapProvider.getModel().getId(), LDAPStorageMapper.class.getName()); + List mapperModels = realm + .getComponentsStream(ldapProvider.getModel().getId(), LDAPStorageMapper.class.getName()) + .collect(Collectors.toList()); ldapQuery.addMappers(mapperModels); return ldapQuery; diff --git a/federation/ldap/src/main/java/org/keycloak/storage/ldap/idm/query/internal/LDAPQuery.java b/federation/ldap/src/main/java/org/keycloak/storage/ldap/idm/query/internal/LDAPQuery.java index b5cbaeb6b1..8eb0bc5f47 100644 --- a/federation/ldap/src/main/java/org/keycloak/storage/ldap/idm/query/internal/LDAPQuery.java +++ b/federation/ldap/src/main/java/org/keycloak/storage/ldap/idm/query/internal/LDAPQuery.java @@ -26,18 +26,14 @@ import org.keycloak.storage.ldap.idm.model.LDAPObject; import org.keycloak.storage.ldap.idm.query.Condition; import org.keycloak.storage.ldap.idm.query.Sort; import org.keycloak.storage.ldap.idm.store.ldap.LDAPContextManager; +import org.keycloak.storage.ldap.mappers.LDAPMappersComparator; import org.keycloak.storage.ldap.mappers.LDAPStorageMapper; import javax.naming.NamingException; import javax.naming.directory.SearchControls; import javax.naming.ldap.LdapContext; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Set; +import java.util.*; import static java.util.Collections.unmodifiableSet; @@ -162,8 +158,10 @@ public class LDAPQuery implements AutoCloseable { public List getResultList() { // Apply mappers now - List sortedMappers = ldapFedProvider.getMapperManager().sortMappersAsc(mappers); - for (ComponentModel mapperModel : sortedMappers) { + LDAPMappersComparator ldapMappersComparator = new LDAPMappersComparator(ldapFedProvider.getLdapIdentityStore().getConfig()); + Collections.sort(mappers, ldapMappersComparator.sortAsc()); + + for (ComponentModel mapperModel : mappers) { LDAPStorageMapper fedMapper = ldapFedProvider.getMapperManager().getMapper(mapperModel); fedMapper.beforeLDAPQuery(this); } diff --git a/federation/ldap/src/main/java/org/keycloak/storage/ldap/mappers/LDAPMappersComparator.java b/federation/ldap/src/main/java/org/keycloak/storage/ldap/mappers/LDAPMappersComparator.java index f659c2b3a9..dc9e3a66ed 100644 --- a/federation/ldap/src/main/java/org/keycloak/storage/ldap/mappers/LDAPMappersComparator.java +++ b/federation/ldap/src/main/java/org/keycloak/storage/ldap/mappers/LDAPMappersComparator.java @@ -18,6 +18,7 @@ package org.keycloak.storage.ldap.mappers; import org.keycloak.component.ComponentModel; +import org.keycloak.models.AuthenticationExecutionModel; import org.keycloak.models.UserModel; import org.keycloak.storage.ldap.LDAPConfig; @@ -34,20 +35,18 @@ import java.util.List; */ public class LDAPMappersComparator { - public static List sortAsc(LDAPConfig ldapConfig, Collection mappers) { - Comparator comparator = new ImportantFirstComparator(ldapConfig); + private LDAPConfig ldapConfig; - List result = new ArrayList<>(mappers); - Collections.sort(result, comparator); - return result; + public LDAPMappersComparator(LDAPConfig ldapConfig) { + this.ldapConfig = ldapConfig; } - public static List sortDesc(LDAPConfig ldapConfig, Collection mappers) { - Comparator comparator = new ImportantFirstComparator(ldapConfig).reversed(); + public Comparator sortAsc() { + return new ImportantFirstComparator(ldapConfig); + } - List result = new ArrayList<>(mappers); - Collections.sort(result, comparator); - return result; + public Comparator sortDesc() { + return new ImportantFirstComparator(ldapConfig).reversed(); } diff --git a/federation/ldap/src/main/java/org/keycloak/storage/ldap/mappers/LDAPStorageMapperManager.java b/federation/ldap/src/main/java/org/keycloak/storage/ldap/mappers/LDAPStorageMapperManager.java index b8e9dc46e4..daf087376d 100644 --- a/federation/ldap/src/main/java/org/keycloak/storage/ldap/mappers/LDAPStorageMapperManager.java +++ b/federation/ldap/src/main/java/org/keycloak/storage/ldap/mappers/LDAPStorageMapperManager.java @@ -17,9 +17,6 @@ package org.keycloak.storage.ldap.mappers; -import java.util.Collection; -import java.util.List; - import org.keycloak.component.ComponentModel; import org.keycloak.models.ModelException; import org.keycloak.storage.ldap.LDAPStorageProvider; @@ -45,15 +42,4 @@ public class LDAPStorageMapperManager { return ldapMapper; } - - - public List sortMappersAsc(Collection mappers) { - return LDAPMappersComparator.sortAsc(ldapProvider.getLdapIdentityStore().getConfig(), mappers); - } - - public List sortMappersDesc(Collection mappers) { - return LDAPMappersComparator.sortDesc(ldapProvider.getLdapIdentityStore().getConfig(), mappers); - } - - } diff --git a/federation/ldap/src/test/java/org/keycloak/storage/ldap/idm/model/LDAPMappersComparatorTest.java b/federation/ldap/src/test/java/org/keycloak/storage/ldap/idm/model/LDAPMappersComparatorTest.java index 41bf3ec9b0..4862c832b3 100644 --- a/federation/ldap/src/test/java/org/keycloak/storage/ldap/idm/model/LDAPMappersComparatorTest.java +++ b/federation/ldap/src/test/java/org/keycloak/storage/ldap/idm/model/LDAPMappersComparatorTest.java @@ -32,6 +32,7 @@ import org.keycloak.storage.ldap.mappers.LDAPStorageMapper; import org.keycloak.storage.ldap.mappers.UserAttributeLDAPStorageMapper; import org.keycloak.storage.ldap.mappers.UserAttributeLDAPStorageMapperFactory; +import java.util.Collections; import java.util.LinkedList; import java.util.List; @@ -46,26 +47,30 @@ public class LDAPMappersComparatorTest { public void testCompareWithCNUsername() { MultivaluedHashMap cfg = new MultivaluedHashMap<>(); cfg.add(LDAPConstants.USERNAME_LDAP_ATTRIBUTE, LDAPConstants.CN); - LDAPConfig config = new LDAPConfig(cfg); + LDAPMappersComparator ldapMappersComparator = new LDAPMappersComparator(new LDAPConfig(cfg)); - List sorted = LDAPMappersComparator.sortAsc(config, getMappers()); - assertOrder(sorted, "username-cn", "sAMAccountName", "first name", "full name"); + List mappers = getMappers(); - sorted = LDAPMappersComparator.sortDesc(config, getMappers()); - assertOrder(sorted, "full name", "first name", "sAMAccountName", "username-cn"); + Collections.sort(mappers, ldapMappersComparator.sortAsc()); + assertOrder(mappers, "username-cn", "sAMAccountName", "first name", "full name"); + + Collections.sort(mappers, ldapMappersComparator.sortDesc()); + assertOrder(mappers, "full name", "first name", "sAMAccountName", "username-cn"); } @Test public void testCompareWithSAMAccountNameUsername() { MultivaluedHashMap cfg = new MultivaluedHashMap<>(); cfg.add(LDAPConstants.USERNAME_LDAP_ATTRIBUTE, LDAPConstants.SAM_ACCOUNT_NAME); - LDAPConfig config = new LDAPConfig(cfg); + LDAPMappersComparator ldapMappersComparator = new LDAPMappersComparator(new LDAPConfig(cfg)); - List sorted = LDAPMappersComparator.sortAsc(config, getMappers()); - assertOrder(sorted, "sAMAccountName", "username-cn", "first name", "full name"); + List mappers = getMappers(); - sorted = LDAPMappersComparator.sortDesc(config, getMappers()); - assertOrder(sorted, "full name", "first name", "username-cn", "sAMAccountName"); + Collections.sort(mappers, ldapMappersComparator.sortAsc()); + assertOrder(mappers, "sAMAccountName", "username-cn", "first name", "full name"); + + Collections.sort(mappers, ldapMappersComparator.sortDesc()); + assertOrder(mappers, "full name", "first name", "username-cn", "sAMAccountName"); } private void assertOrder(List result, String... names) { diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmAdapter.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmAdapter.java index 3af7ad6238..e9b0bc0137 100755 --- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmAdapter.java +++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmAdapter.java @@ -638,9 +638,9 @@ public class RealmAdapter implements CachedRealmModel { } @Override - public List getRequiredCredentials() { - if (isUpdated()) return updated.getRequiredCredentials(); - return cached.getRequiredCredentials(); + public Stream getRequiredCredentialsStream() { + if (isUpdated()) return updated.getRequiredCredentialsStream(); + return cached.getRequiredCredentials().stream(); } @Override @@ -833,21 +833,18 @@ public class RealmAdapter implements CachedRealmModel { @Override - public List getIdentityProviders() { - if (isUpdated()) return updated.getIdentityProviders(); - return cached.getIdentityProviders(); + public Stream getIdentityProvidersStream() { + if (isUpdated()) return updated.getIdentityProvidersStream(); + return cached.getIdentityProviders().stream(); } @Override public IdentityProviderModel getIdentityProviderByAlias(String alias) { if (isUpdated()) return updated.getIdentityProviderByAlias(alias); - for (IdentityProviderModel identityProviderModel : getIdentityProviders()) { - if (identityProviderModel.getAlias().equals(alias)) { - return identityProviderModel; - } - } - - return null; + return getIdentityProvidersStream() + .filter(model -> Objects.equals(model.getAlias(), alias)) + .findFirst() + .orElse(null); } @Override @@ -953,9 +950,9 @@ public class RealmAdapter implements CachedRealmModel { } @Override - public Set getEventsListeners() { - if (isUpdated()) return updated.getEventsListeners(); - return cached.getEventsListeners(); + public Stream getEventsListenersStream() { + if (isUpdated()) return updated.getEventsListenersStream(); + return cached.getEventsListeners().stream(); } @Override @@ -965,9 +962,9 @@ public class RealmAdapter implements CachedRealmModel { } @Override - public Set getEnabledEventTypes() { - if (isUpdated()) return updated.getEnabledEventTypes(); - return cached.getEnabledEventTypes(); + public Stream getEnabledEventTypesStream() { + if (isUpdated()) return updated.getEnabledEventTypesStream(); + return cached.getEnabledEventTypes().stream(); } @Override @@ -1081,9 +1078,9 @@ public class RealmAdapter implements CachedRealmModel { } @Override - public Set getSupportedLocales() { - if (isUpdated()) return updated.getSupportedLocales(); - return cached.getSupportedLocales(); + public Stream getSupportedLocalesStream() { + if (isUpdated()) return updated.getSupportedLocalesStream(); + return cached.getSupportedLocales().stream(); } @Override @@ -1104,20 +1101,16 @@ public class RealmAdapter implements CachedRealmModel { } @Override - public Set getIdentityProviderMappers() { - if (isUpdated()) return updated.getIdentityProviderMappers(); - return cached.getIdentityProviderMapperSet(); + public Stream getIdentityProviderMappersStream() { + if (isUpdated()) return updated.getIdentityProviderMappersStream(); + return cached.getIdentityProviderMapperSet().stream(); } @Override - public Set getIdentityProviderMappersByAlias(String brokerAlias) { - if (isUpdated()) return updated.getIdentityProviderMappersByAlias(brokerAlias); - Set mappings = new HashSet<>(); - List list = cached.getIdentityProviderMappers().getList(brokerAlias); - for (IdentityProviderMapperModel entity : list) { - mappings.add(entity); - } - return Collections.unmodifiableSet(mappings); + public Stream getIdentityProviderMappersByAliasStream(String brokerAlias) { + if (isUpdated()) return updated.getIdentityProviderMappersByAliasStream(brokerAlias); + Set mappings = new HashSet<>(cached.getIdentityProviderMappers().getList(brokerAlias)); + return mappings.stream(); } @Override @@ -1236,29 +1229,25 @@ public class RealmAdapter implements CachedRealmModel { } @Override - public List getAuthenticationFlows() { - if (isUpdated()) return updated.getAuthenticationFlows(); - return cached.getAuthenticationFlowList(); + public Stream getAuthenticationFlowsStream() { + if (isUpdated()) return updated.getAuthenticationFlowsStream(); + return cached.getAuthenticationFlowList().stream(); } @Override public AuthenticationFlowModel getFlowByAlias(String alias) { - for (AuthenticationFlowModel flow : getAuthenticationFlows()) { - if (flow.getAlias().equals(alias)) { - return flow; - } - } - return null; + return getAuthenticationFlowsStream() + .filter(flow -> Objects.equals(flow.getAlias(), alias)) + .findFirst() + .orElse(null); } @Override public AuthenticatorConfigModel getAuthenticatorConfigByAlias(String alias) { - for (AuthenticatorConfigModel config : getAuthenticatorConfigs()) { - if (config.getAlias().equals(alias)) { - return config; - } - } - return null; + return getAuthenticatorConfigsStream() + .filter(config -> Objects.equals(config.getAlias(), alias)) + .findFirst() + .orElse(null); } @@ -1289,9 +1278,9 @@ public class RealmAdapter implements CachedRealmModel { } @Override - public List getAuthenticationExecutions(String flowId) { - if (isUpdated()) return updated.getAuthenticationExecutions(flowId); - return cached.getAuthenticationExecutions().get(flowId); + public Stream getAuthenticationExecutionsStream(String flowId) { + if (isUpdated()) return updated.getAuthenticationExecutionsStream(flowId); + return cached.getAuthenticationExecutions().get(flowId).stream(); } @Override @@ -1327,11 +1316,9 @@ public class RealmAdapter implements CachedRealmModel { } @Override - public List getAuthenticatorConfigs() { - if (isUpdated()) return updated.getAuthenticatorConfigs(); - List models = new ArrayList<>(); - models.addAll(cached.getAuthenticatorConfigs().values()); - return Collections.unmodifiableList(models); + public Stream getAuthenticatorConfigsStream() { + if (isUpdated()) return updated.getAuthenticatorConfigsStream(); + return cached.getAuthenticatorConfigs().values().stream(); } @Override @@ -1361,9 +1348,9 @@ public class RealmAdapter implements CachedRealmModel { } @Override - public List getRequiredActionProviders() { - if (isUpdated()) return updated.getRequiredActionProviders(); - return cached.getRequiredActionProviderList(); + public Stream getRequiredActionProvidersStream() { + if (isUpdated()) return updated.getRequiredActionProvidersStream(); + return cached.getRequiredActionProviderList().stream(); } @Override @@ -1449,20 +1436,15 @@ public class RealmAdapter implements CachedRealmModel { } @Override - public List getClientScopes() { - if (isUpdated()) return updated.getClientScopes(); - List clientScopes = cached.getClientScopes(); - if (clientScopes.isEmpty()) return Collections.EMPTY_LIST; - List apps = new LinkedList<>(); - for (String id : clientScopes) { - ClientScopeModel model = cacheSession.getClientScopeById(id, this); + public Stream getClientScopesStream() { + if (isUpdated()) return updated.getClientScopesStream(); + return cached.getClientScopes().stream().map(scope -> { + ClientScopeModel model = cacheSession.getClientScopeById(scope, this); if (model == null) { - throw new IllegalStateException("Cached clientScope not found: " + id); + throw new IllegalStateException("Cached clientScope not found: " + scope); } - apps.add(model); - } - return Collections.unmodifiableList(apps); - + return model; + }); } @Override @@ -1507,19 +1489,12 @@ public class RealmAdapter implements CachedRealmModel { } @Override - public List getDefaultClientScopes(boolean defaultScope) { - if (isUpdated()) return updated.getDefaultClientScopes(defaultScope); - + public Stream getDefaultClientScopesStream(boolean defaultScope) { + if (isUpdated()) return updated.getDefaultClientScopesStream(defaultScope); List clientScopeIds = defaultScope ? cached.getDefaultDefaultClientScopes() : cached.getOptionalDefaultClientScopes(); - - List clientScopes = new LinkedList<>(); - for (String scopeId : clientScopeIds) { - ClientScopeModel clientScope = cacheSession.getClientScopeById(scopeId, this); - if (clientScope != null) { - clientScopes.add(clientScope); - } - } - return clientScopes; + return clientScopeIds.stream() + .map(scope -> cacheSession.getClientScopeById(scope, this)) + .filter(Objects::nonNull); } @Override @@ -1588,27 +1563,21 @@ public class RealmAdapter implements CachedRealmModel { } @Override - public List getComponents(String parentId, String providerType) { - if (isUpdated()) return updated.getComponents(parentId, providerType); - List components = cached.getComponentsByParentAndType().getList(parentId + providerType); - if (components == null) return Collections.EMPTY_LIST; - return Collections.unmodifiableList(components); + public Stream getComponentsStream(String parentId, String providerType) { + if (isUpdated()) return updated.getComponentsStream(parentId, providerType); + return cached.getComponentsByParentAndType().getList(parentId + providerType).stream(); } @Override - public List getComponents(String parentId) { - if (isUpdated()) return updated.getComponents(parentId); - List components = cached.getComponentsByParent().getList(parentId); - if (components == null) return Collections.EMPTY_LIST; - return Collections.unmodifiableList(components); + public Stream getComponentsStream(String parentId) { + if (isUpdated()) return updated.getComponentsStream(parentId); + return cached.getComponentsByParent().getList(parentId).stream(); } @Override - public List getComponents() { - if (isUpdated()) return updated.getComponents(); - List results = new LinkedList<>(); - results.addAll(cached.getComponents().values()); - return Collections.unmodifiableList(results); + public Stream getComponentsStream() { + if (isUpdated()) return updated.getComponentsStream(); + return cached.getComponents().values().stream(); } @Override diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmCacheSession.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmCacheSession.java index a7e7e95a68..e68e16d0b8 100755 --- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmCacheSession.java +++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmCacheSession.java @@ -468,27 +468,20 @@ public class RealmCacheSession implements CacheRealmProvider { } @Override - public List getRealmsWithProviderType(Class type) { + public Stream getRealmsWithProviderTypeStream(Class type) { // Retrieve realms from backend - List backendRealms = getRealmDelegate().getRealmsWithProviderType(type); - return getRealms(backendRealms); + return getRealms(getRealmDelegate().getRealmsWithProviderTypeStream(type)); } @Override - public List getRealms() { + public Stream getRealmsStream() { // Retrieve realms from backend - List backendRealms = getRealmDelegate().getRealms(); - return getRealms(backendRealms); + return getRealms(getRealmDelegate().getRealmsStream()); } - private List getRealms(List backendRealms) { + private Stream getRealms(Stream backendRealms) { // Return cache delegates to ensure cache invalidated during write operations - List cachedRealms = new LinkedList<>(); - for (RealmModel realm : backendRealms) { - RealmModel cached = getRealm(realm.getId()); - cachedRealms.add(cached); - } - return cachedRealms; + return backendRealms.map(RealmModel::getId).map(this::getRealm); } @Override @@ -1240,8 +1233,8 @@ public class RealmCacheSession implements CacheRealmProvider { } @Override - public List listClientInitialAccess(RealmModel realm) { - return getRealmDelegate().listClientInitialAccess(realm); + public Stream listClientInitialAccessStream(RealmModel realm) { + return getRealmDelegate().listClientInitialAccessStream(realm); } @Override diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/entities/CachedRealm.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/entities/CachedRealm.java index ff2460d0ab..ccdf445deb 100755 --- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/entities/CachedRealm.java +++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/entities/CachedRealm.java @@ -35,7 +35,6 @@ import org.keycloak.models.RequiredActionProviderModel; import org.keycloak.models.RequiredCredentialModel; import org.keycloak.models.WebAuthnPolicy; -import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -43,6 +42,7 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.function.Function; import java.util.stream.Collectors; /** @@ -113,14 +113,14 @@ public class CachedRealm extends AbstractExtendableRevisioned { protected List requiredCredentials; protected MultivaluedHashMap componentsByParent = new MultivaluedHashMap<>(); protected MultivaluedHashMap componentsByParentAndType = new MultivaluedHashMap<>(); - protected Map components = new HashMap<>(); + protected Map components; protected List identityProviders; protected Map browserSecurityHeaders; protected Map smtpConfig; protected Map authenticationFlows = new HashMap<>(); protected List authenticationFlowList; - protected Map authenticatorConfigs = new HashMap<>(); + protected Map authenticatorConfigs; protected Map requiredActionProviders = new HashMap<>(); protected List requiredActionProviderList; protected Map requiredActionProvidersByAlias = new HashMap<>(); @@ -224,17 +224,14 @@ public class CachedRealm extends AbstractExtendableRevisioned { adminTheme = model.getAdminTheme(); emailTheme = model.getEmailTheme(); - requiredCredentials = model.getRequiredCredentials(); + requiredCredentials = model.getRequiredCredentialsStream().collect(Collectors.toList()); userActionTokenLifespans = Collections.unmodifiableMap(new HashMap<>(model.getUserActionTokenLifespans())); - this.identityProviders = new ArrayList<>(); - - for (IdentityProviderModel identityProviderModel : model.getIdentityProviders()) { - this.identityProviders.add(new IdentityProviderModel(identityProviderModel)); - } + this.identityProviders = model.getIdentityProvidersStream().map(IdentityProviderModel::new) + .collect(Collectors.toList()); this.identityProviders = Collections.unmodifiableList(this.identityProviders); - this.identityProviderMapperSet = model.getIdentityProviderMappers(); + this.identityProviderMapperSet = model.getIdentityProviderMappersStream().collect(Collectors.toSet()); for (IdentityProviderMapperModel mapper : identityProviderMapperSet) { identityProviderMappers.add(mapper.getIdentityProviderAlias(), mapper); } @@ -246,8 +243,8 @@ public class CachedRealm extends AbstractExtendableRevisioned { eventsEnabled = model.isEventsEnabled(); eventsExpiration = model.getEventsExpiration(); - eventsListeners = model.getEventsListeners(); - enabledEventTypes = model.getEnabledEventTypes(); + eventsListeners = model.getEventsListenersStream().collect(Collectors.toSet()); + enabledEventTypes = model.getEnabledEventTypesStream().collect(Collectors.toSet()); adminEventsEnabled = model.isAdminEventsEnabled(); adminEventsDetailsEnabled = model.isAdminEventsDetailsEnabled(); @@ -259,25 +256,24 @@ public class CachedRealm extends AbstractExtendableRevisioned { cacheClientScopes(model); internationalizationEnabled = model.isInternationalizationEnabled(); - supportedLocales = model.getSupportedLocales(); + supportedLocales = model.getSupportedLocalesStream().collect(Collectors.toSet()); defaultLocale = model.getDefaultLocale(); - authenticationFlowList = model.getAuthenticationFlows(); + authenticationFlowList = model.getAuthenticationFlowsStream().collect(Collectors.toList()); for (AuthenticationFlowModel flow : authenticationFlowList) { this.authenticationFlows.put(flow.getId(), flow); authenticationExecutions.put(flow.getId(), new LinkedList<>()); - for (AuthenticationExecutionModel execution : model.getAuthenticationExecutions(flow.getId())) { + model.getAuthenticationExecutionsStream(flow.getId()).forEachOrdered(execution -> { authenticationExecutions.add(flow.getId(), execution); executionsById.put(execution.getId(), execution); if (execution.getFlowId() != null) { executionsByFlowId.put(execution.getFlowId(), execution); } - } + }); } - for (AuthenticatorConfigModel authenticator : model.getAuthenticatorConfigs()) { - authenticatorConfigs.put(authenticator.getId(), authenticator); - } - requiredActionProviderList = model.getRequiredActionProviders(); + authenticatorConfigs = model.getAuthenticatorConfigsStream() + .collect(Collectors.toMap(AuthenticatorConfigModel::getId, Function.identity())); + requiredActionProviderList = model.getRequiredActionProvidersStream().collect(Collectors.toList()); for (RequiredActionProviderModel action : requiredActionProviderList) { this.requiredActionProviders.put(action.getId(), action); requiredActionProvidersByAlias.put(action.getAlias(), action); @@ -292,15 +288,13 @@ public class CachedRealm extends AbstractExtendableRevisioned { clientAuthenticationFlow = model.getClientAuthenticationFlow(); dockerAuthenticationFlow = model.getDockerAuthenticationFlow(); - for (ComponentModel component : model.getComponents()) { - componentsByParentAndType.add(component.getParentId() + component.getProviderType(), component); - } - for (ComponentModel component : model.getComponents()) { - componentsByParent.add(component.getParentId(), component); - } - for (ComponentModel component : model.getComponents()) { - components.put(component.getId(), component); - } + model.getComponentsStream().forEach(component -> + componentsByParentAndType.add(component.getParentId() + component.getProviderType(), component) + ); + model.getComponentsStream().forEach(component -> + componentsByParent.add(component.getParentId(), component) + ); + components = model.getComponentsStream().collect(Collectors.toMap(component -> component.getId(), Function.identity())); try { attributes = model.getAttributes(); @@ -310,15 +304,11 @@ public class CachedRealm extends AbstractExtendableRevisioned { } protected void cacheClientScopes(RealmModel model) { - for (ClientScopeModel clientScope : model.getClientScopes()) { - clientScopes.add(clientScope.getId()); - } - for (ClientScopeModel clientScope : model.getDefaultClientScopes(true)) { - defaultDefaultClientScopes.add(clientScope.getId()); - } - for (ClientScopeModel clientScope : model.getDefaultClientScopes(false)) { - optionalDefaultClientScopes.add(clientScope.getId()); - } + clientScopes = model.getClientScopesStream().map(ClientScopeModel::getId).collect(Collectors.toList()); + defaultDefaultClientScopes = model.getDefaultClientScopesStream(true).map(ClientScopeModel::getId) + .collect(Collectors.toList()); + optionalDefaultClientScopes = model.getDefaultClientScopesStream(false).map(ClientScopeModel::getId) + .collect(Collectors.toList()); } public String getMasterAdminClient() { diff --git a/model/jpa/src/main/java/org/keycloak/events/jpa/JpaAdminEventQuery.java b/model/jpa/src/main/java/org/keycloak/events/jpa/JpaAdminEventQuery.java index 15c58c225c..d0a892baf7 100755 --- a/model/jpa/src/main/java/org/keycloak/events/jpa/JpaAdminEventQuery.java +++ b/model/jpa/src/main/java/org/keycloak/events/jpa/JpaAdminEventQuery.java @@ -33,6 +33,9 @@ import java.util.ArrayList; import java.util.Date; import java.util.LinkedList; import java.util.List; +import java.util.stream.Stream; + +import static org.keycloak.utils.StreamsUtil.closing; /** * @author Giriraj Sharma @@ -140,7 +143,7 @@ public class JpaAdminEventQuery implements AdminEventQuery { } @Override - public List getResultList() { + public Stream getResultStream() { if (!predicates.isEmpty()) { cq.where(cb.and(predicates.toArray(new Predicate[predicates.size()]))); } @@ -157,12 +160,7 @@ public class JpaAdminEventQuery implements AdminEventQuery { query.setMaxResults(maxResults); } - List events = new LinkedList(); - for (AdminEventEntity e : query.getResultList()) { - events.add(JpaEventStoreProvider.convertAdminEvent(e)); - } - - return events; + return closing(query.getResultStream().map(JpaEventStoreProvider::convertAdminEvent)); } } diff --git a/model/jpa/src/main/java/org/keycloak/events/jpa/JpaEventQuery.java b/model/jpa/src/main/java/org/keycloak/events/jpa/JpaEventQuery.java index 4f7a999c82..c3e2035c42 100644 --- a/model/jpa/src/main/java/org/keycloak/events/jpa/JpaEventQuery.java +++ b/model/jpa/src/main/java/org/keycloak/events/jpa/JpaEventQuery.java @@ -31,6 +31,9 @@ import java.util.ArrayList; import java.util.Date; import java.util.LinkedList; import java.util.List; +import java.util.stream.Stream; + +import static org.keycloak.utils.StreamsUtil.closing; /** * @author Stian Thorgersen @@ -113,7 +116,7 @@ public class JpaEventQuery implements EventQuery { } @Override - public List getResultList() { + public Stream getResultStream() { if (!predicates.isEmpty()) { cq.where(cb.and(predicates.toArray(new Predicate[predicates.size()]))); } @@ -130,12 +133,8 @@ public class JpaEventQuery implements EventQuery { query.setMaxResults(maxResults); } - List events = new LinkedList(); - for (EventEntity e : query.getResultList()) { - events.add(JpaEventStoreProvider.convertEvent(e)); - } - return events; + return closing(query.getResultStream().map(JpaEventStoreProvider::convertEvent)); } } diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaRealmProvider.java b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaRealmProvider.java index 978a5d4dcb..7bcca946bf 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaRealmProvider.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaRealmProvider.java @@ -110,26 +110,20 @@ public class JpaRealmProvider implements RealmProvider, ClientProvider, GroupPro } @Override - public List getRealmsWithProviderType(Class providerType) { + public Stream getRealmsWithProviderTypeStream(Class providerType) { TypedQuery query = em.createNamedQuery("getRealmIdsWithProviderType", String.class); query.setParameter("providerType", providerType.getName()); return getRealms(query); } @Override - public List getRealms() { + public Stream getRealmsStream() { TypedQuery query = em.createNamedQuery("getAllRealmIds", String.class); return getRealms(query); } - private List getRealms(TypedQuery query) { - List entities = query.getResultList(); - List realms = new ArrayList(); - for (String id : entities) { - RealmModel realm = session.realms().getRealm(id); - if (realm != null) realms.add(realm); - } - return realms; + private Stream getRealms(TypedQuery query) { + return closing(query.getResultStream().map(session.realms()::getRealm).filter(Objects::nonNull)); } @Override @@ -843,16 +837,12 @@ public class JpaRealmProvider implements RealmProvider, ClientProvider, GroupPro } @Override - public List listClientInitialAccess(RealmModel realm) { + public Stream listClientInitialAccessStream(RealmModel realm) { RealmEntity realmEntity = em.find(RealmEntity.class, realm.getId()); TypedQuery query = em.createNamedQuery("findClientInitialAccessByRealm", ClientInitialAccessEntity.class); query.setParameter("realm", realmEntity); - List entities = query.getResultList(); - - return entities.stream() - .map(this::entityToModel) - .collect(Collectors.toList()); + return closing(query.getResultStream().map(this::entityToModel)); } @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 d5f4daa8ec..7d2aae036c 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 @@ -57,15 +57,7 @@ import javax.persistence.criteria.Expression; import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Root; import javax.persistence.criteria.Subquery; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.stream.Collectors; import javax.persistence.LockModeType; @@ -114,12 +106,14 @@ public class JpaUserProvider implements UserProvider, UserCredentialStore { realm.getDefaultGroupsStream().forEach(userModel::joinGroupImpl); } - if (addDefaultRequiredActions){ - for (RequiredActionProviderModel r : realm.getRequiredActionProviders()) { - if (r.isEnabled() && r.isDefaultAction()) { - userModel.addRequiredAction(r.getAlias()); - } - } + if (addDefaultRequiredActions) { + Optional requiredAction = realm.getRequiredActionProvidersStream() + .filter(RequiredActionProviderModel::isEnabled) + .filter(RequiredActionProviderModel::isDefaultAction) + .map(RequiredActionProviderModel::getAlias) + .findFirst(); + if (requiredAction.isPresent()) + userModel.addRequiredAction(requiredAction.get()); } return userModel; diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java index 2d43a8d67d..5c16154d71 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java @@ -33,10 +33,10 @@ import javax.persistence.LockModeType; import javax.persistence.TypedQuery; import java.util.*; import java.util.function.Predicate; -import java.util.stream.Collectors; import java.util.stream.Stream; import static java.util.Objects.nonNull; +import static org.keycloak.utils.StreamsUtil.closing; /** * @author Bill Burke @@ -701,19 +701,8 @@ public class RealmAdapter implements RealmModel, JpaModel { @Override - public List getRequiredCredentials() { - Collection entities = realm.getRequiredCredentials(); - if (entities == null) return Collections.EMPTY_LIST; - List requiredCredentialModels = new LinkedList<>(); - for (RequiredCredentialEntity entity : entities) { - RequiredCredentialModel model = new RequiredCredentialModel(); - model.setFormLabel(entity.getFormLabel()); - model.setType(entity.getType()); - model.setSecret(entity.isSecret()); - model.setInput(entity.isInput()); - requiredCredentialModels.add(model); - } - return Collections.unmodifiableList(requiredCredentialModels); + public Stream getRequiredCredentialsStream() { + return realm.getRequiredCredentials().stream().map(this::toRequiredCredentialModel); } @@ -1179,12 +1168,8 @@ public class RealmAdapter implements RealmModel, JpaModel { } @Override - public Set getEventsListeners() { - Set eventsListeners = realm.getEventsListeners(); - if (eventsListeners.isEmpty()) return Collections.EMPTY_SET; - Set copy = new HashSet<>(); - copy.addAll(eventsListeners); - return Collections.unmodifiableSet(copy); + public Stream getEventsListenersStream() { + return realm.getEventsListeners().stream(); } @Override @@ -1194,12 +1179,8 @@ public class RealmAdapter implements RealmModel, JpaModel { } @Override - public Set getEnabledEventTypes() { - Set enabledEventTypes = realm.getEnabledEventTypes(); - if (enabledEventTypes.isEmpty()) return Collections.EMPTY_SET; - Set copy = new HashSet<>(); - copy.addAll(enabledEventTypes); - return Collections.unmodifiableSet(copy); + public Stream getEnabledEventTypesStream() { + return realm.getEnabledEventTypes().stream(); } @Override @@ -1250,18 +1231,8 @@ public class RealmAdapter implements RealmModel, JpaModel { } @Override - public List getIdentityProviders() { - List entities = realm.getIdentityProviders(); - if (entities.isEmpty()) return Collections.EMPTY_LIST; - List identityProviders = new ArrayList(); - - for (IdentityProviderEntity entity: entities) { - IdentityProviderModel identityProviderModel = entityToModel(entity); - - identityProviders.add(identityProviderModel); - } - - return Collections.unmodifiableList(identityProviders); + public Stream getIdentityProvidersStream() { + return realm.getIdentityProviders().stream().map(this::entityToModel); } private IdentityProviderModel entityToModel(IdentityProviderEntity entity) { @@ -1288,13 +1259,10 @@ public class RealmAdapter implements RealmModel, JpaModel { @Override public IdentityProviderModel getIdentityProviderByAlias(String alias) { - for (IdentityProviderModel identityProviderModel : getIdentityProviders()) { - if (identityProviderModel.getAlias().equals(alias)) { - return identityProviderModel; - } - } - - return null; + return getIdentityProvidersStream() + .filter(model -> Objects.equals(model.getAlias(), alias)) + .findFirst() + .orElse(null); } @Override @@ -1414,12 +1382,8 @@ public class RealmAdapter implements RealmModel, JpaModel { } @Override - public Set getSupportedLocales() { - Set supportedLocales = realm.getSupportedLocales(); - if (supportedLocales == null || supportedLocales.isEmpty()) return Collections.EMPTY_SET; - Set copy = new HashSet<>(); - copy.addAll(supportedLocales); - return Collections.unmodifiableSet(copy); + public Stream getSupportedLocalesStream() { + return realm.getSupportedLocales().stream(); } @Override @@ -1440,28 +1404,15 @@ public class RealmAdapter implements RealmModel, JpaModel { } @Override - public Set getIdentityProviderMappers() { - Collection entities = this.realm.getIdentityProviderMappers(); - if (entities.isEmpty()) return Collections.EMPTY_SET; - Set mappings = new HashSet(); - for (IdentityProviderMapperEntity entity : entities) { - IdentityProviderMapperModel mapping = entityToModel(entity); - mappings.add(mapping); - } - return Collections.unmodifiableSet(mappings); + public Stream getIdentityProviderMappersStream() { + return realm.getIdentityProviderMappers().stream().map(this::entityToModel); } @Override - public Set getIdentityProviderMappersByAlias(String brokerAlias) { - Set mappings = new HashSet(); - for (IdentityProviderMapperEntity entity : this.realm.getIdentityProviderMappers()) { - if (!entity.getIdentityProviderAlias().equals(brokerAlias)) { - continue; - } - IdentityProviderMapperModel mapping = entityToModel(entity); - mappings.add(mapping); - } - return mappings; + public Stream getIdentityProviderMappersByAliasStream(String brokerAlias) { + return realm.getIdentityProviderMappers().stream() + .filter(e -> Objects.equals(e.getIdentityProviderAlias(), brokerAlias)) + .map(this::entityToModel); } @Override @@ -1630,31 +1581,24 @@ public class RealmAdapter implements RealmModel, JpaModel { } @Override - public List getAuthenticationFlows() { - return realm.getAuthenticationFlows().stream() - .map(this::entityToModel) - .collect(Collectors.collectingAndThen( - Collectors.toList(), Collections::unmodifiableList)); + public Stream getAuthenticationFlowsStream() { + return realm.getAuthenticationFlows().stream().map(this::entityToModel); } @Override public AuthenticationFlowModel getFlowByAlias(String alias) { - for (AuthenticationFlowModel flow : getAuthenticationFlows()) { - if (flow.getAlias().equals(alias)) { - return flow; - } - } - return null; + return getAuthenticationFlowsStream() + .filter(flow -> Objects.equals(flow.getAlias(), alias)) + .findFirst() + .orElse(null); } @Override public AuthenticatorConfigModel getAuthenticatorConfigByAlias(String alias) { - for (AuthenticatorConfigModel config : getAuthenticatorConfigs()) { - if (config.getAlias().equals(alias)) { - return config; - } - } - return null; + return getAuthenticatorConfigsStream() + .filter(config -> Objects.equals(config.getAlias(), alias)) + .findFirst() + .orElse(null); } protected AuthenticationFlowModel entityToModel(AuthenticationFlowEntity entity) { @@ -1725,15 +1669,13 @@ public class RealmAdapter implements RealmModel, JpaModel { } @Override - public List getAuthenticationExecutions(String flowId) { + public Stream getAuthenticationExecutionsStream(String flowId) { AuthenticationFlowEntity flow = em.getReference(AuthenticationFlowEntity.class, flowId); return flow.getExecutions().stream() .filter(e -> getId().equals(e.getRealm().getId())) .map(this::entityToModel) - .sorted(AuthenticationExecutionModel.ExecutionComparator.SINGLETON) - .collect(Collectors.collectingAndThen( - Collectors.toList(), Collections::unmodifiableList)); + .sorted(AuthenticationExecutionModel.ExecutionComparator.SINGLETON); } public AuthenticationExecutionModel entityToModel(AuthenticationExecutionEntity entity) { @@ -1889,14 +1831,8 @@ public class RealmAdapter implements RealmModel, JpaModel { } @Override - public List getAuthenticatorConfigs() { - Collection entities = realm.getAuthenticatorConfigs(); - if (entities.isEmpty()) return Collections.EMPTY_LIST; - List authenticators = new LinkedList<>(); - for (AuthenticatorConfigEntity entity : entities) { - authenticators.add(entityToModel(entity)); - } - return Collections.unmodifiableList(authenticators); + public Stream getAuthenticatorConfigsStream() { + return realm.getAuthenticatorConfigs().stream().map(this::entityToModel); } @Override @@ -1973,15 +1909,10 @@ public class RealmAdapter implements RealmModel, JpaModel { } @Override - public List getRequiredActionProviders() { - Collection entities = realm.getRequiredActionProviders(); - if (entities.isEmpty()) return Collections.EMPTY_LIST; - List actions = new LinkedList<>(); - for (RequiredActionProviderEntity entity : entities) { - actions.add(entityToModel(entity)); - } - Collections.sort(actions, RequiredActionProviderModel.RequiredActionComparator.SINGLETON); - return Collections.unmodifiableList(actions); + public Stream getRequiredActionProvidersStream() { + return realm.getRequiredActionProviders().stream() + .map(this::entityToModel) + .sorted(RequiredActionProviderModel.RequiredActionComparator.SINGLETON); } private RequiredActionProviderEntity getRequiredProviderEntity(String id, boolean readForRemove) { @@ -1995,10 +1926,10 @@ public class RealmAdapter implements RealmModel, JpaModel { @Override public RequiredActionProviderModel getRequiredActionProviderByAlias(String alias) { - for (RequiredActionProviderModel action : getRequiredActionProviders()) { - if (action.getAlias().equals(alias)) return action; - } - return null; + return getRequiredActionProvidersStream() + .filter(action -> Objects.equals(action.getAlias(), alias)) + .findFirst() + .orElse(null); } @Override @@ -2052,14 +1983,8 @@ public class RealmAdapter implements RealmModel, JpaModel { } @Override - public List getClientScopes() { - Collection entities = realm.getClientScopes(); - if (entities == null || entities.isEmpty()) return Collections.EMPTY_LIST; - List list = new LinkedList<>(); - for (ClientScopeEntity entity : entities) { - list.add(session.realms().getClientScopeById(entity.getId(), this)); - } - return Collections.unmodifiableList(list); + public Stream getClientScopesStream() { + return realm.getClientScopes().stream().map(ClientScopeEntity::getId).map(this::getClientScopeById); } @Override @@ -2142,19 +2067,11 @@ public class RealmAdapter implements RealmModel, JpaModel { } @Override - public List getDefaultClientScopes(boolean defaultScope) { + public Stream getDefaultClientScopesStream(boolean defaultScope) { TypedQuery query = em.createNamedQuery("defaultClientScopeRealmMappingIdsByRealm", String.class); query.setParameter("realm", getEntity()); query.setParameter("defaultScope", defaultScope); - List ids = query.getResultList(); - - List clientScopes = new LinkedList<>(); - for (String clientScopeId : ids) { - ClientScopeModel clientScope = getClientScopeById(clientScopeId); - if (clientScope == null) continue; - clientScopes.add(clientScope); - } - return clientScopes; + return closing(query.getResultStream().map(this::getClientScopeById).filter(Objects::nonNull)); } @Override @@ -2273,23 +2190,22 @@ public class RealmAdapter implements RealmModel, JpaModel { } @Override - public List getComponents(String parentId, final String providerType) { + public Stream getComponentsStream(String parentId, final String providerType) { if (parentId == null) parentId = getId(); final String parent = parentId; - return realm.getComponents().stream() - .filter(c -> parent.equals(c.getParentId()) - && providerType.equals(c.getProviderType())) - .map(this::entityToModel) - .collect(Collectors.toList()); + Stream componentStream = realm.getComponents().stream() + .filter(c -> Objects.equals(parent, c.getParentId())); + + if (providerType != null) { + componentStream = componentStream.filter(c -> Objects.equals(providerType, c.getProviderType())); + } + return componentStream.map(this::entityToModel); } @Override - public List getComponents(final String parentId) { - return realm.getComponents().stream() - .filter(c -> parentId.equals(c.getParentId())) - .map(this::entityToModel) - .collect(Collectors.toList()); + public Stream getComponentsStream(final String parentId) { + return getComponentsStream(parentId, null); } protected ComponentModel entityToModel(ComponentEntity c) { @@ -2308,9 +2224,18 @@ public class RealmAdapter implements RealmModel, JpaModel { return model; } + private RequiredCredentialModel toRequiredCredentialModel(RequiredCredentialEntity entity) { + RequiredCredentialModel model = new RequiredCredentialModel(); + model.setFormLabel(entity.getFormLabel()); + model.setType(entity.getType()); + model.setSecret(entity.isSecret()); + model.setInput(entity.isInput()); + return model; + } + @Override - public List getComponents() { - return realm.getComponents().stream().map(this::entityToModel).collect(Collectors.toList()); + public Stream getComponentsStream() { + return realm.getComponents().stream().map(this::entityToModel); } @Override diff --git a/server-spi-private/src/main/java/org/keycloak/events/EventBuilder.java b/server-spi-private/src/main/java/org/keycloak/events/EventBuilder.java index 369e28cc47..ea29b775e5 100755 --- a/server-spi-private/src/main/java/org/keycloak/events/EventBuilder.java +++ b/server-spi-private/src/main/java/org/keycloak/events/EventBuilder.java @@ -27,9 +27,10 @@ import org.keycloak.models.UserModel; import org.keycloak.models.UserSessionModel; import java.util.HashMap; -import java.util.LinkedList; import java.util.List; import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; /** * @author Stian Thorgersen @@ -57,17 +58,19 @@ public class EventBuilder { } } - if (realm.getEventsListeners() != null && !realm.getEventsListeners().isEmpty()) { - this.listeners = new LinkedList<>(); - for (String id : realm.getEventsListeners()) { - EventListenerProvider listener = session.getProvider(EventListenerProvider.class, id); - if (listener != null) { - listeners.add(listener); - } else { - log.error("Event listener '" + id + "' registered, but provider not found"); - } - } - } + + this.listeners = realm.getEventsListenersStream() + .map(id -> { + EventListenerProvider listener = session.getProvider(EventListenerProvider.class, id); + if (listener != null) { + return listener; + } else { + log.error("Event listener '" + id + "' registered, but provider not found"); + return null; + } + }) + .filter(Objects::nonNull) + .collect(Collectors.toList()); realm(realm); ipAddress(clientConnection.getRemoteAddr()); @@ -177,7 +180,8 @@ public class EventBuilder { event.setTime(Time.currentTimeMillis()); if (store != null) { - if (realm.getEnabledEventTypes() != null && !realm.getEnabledEventTypes().isEmpty() ? realm.getEnabledEventTypes().contains(event.getType().name()) : event.getType().isSaveByDefault()) { + Set eventTypes = realm.getEnabledEventTypesStream().collect(Collectors.toSet()); + if (!eventTypes.isEmpty() ? eventTypes.contains(event.getType().name()) : event.getType().isSaveByDefault()) { try { store.onEvent(event); } catch (Throwable t) { diff --git a/server-spi-private/src/main/java/org/keycloak/events/EventQuery.java b/server-spi-private/src/main/java/org/keycloak/events/EventQuery.java index dac4b251a8..57687f93cd 100644 --- a/server-spi-private/src/main/java/org/keycloak/events/EventQuery.java +++ b/server-spi-private/src/main/java/org/keycloak/events/EventQuery.java @@ -19,6 +19,8 @@ package org.keycloak.events; import java.util.Date; import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; /** * @author Stian Thorgersen @@ -43,6 +45,17 @@ public interface EventQuery { EventQuery maxResults(int results); - List getResultList(); + /** + * @deprecated Use {@link #getResultStream() getResultStream} instead. + */ + @Deprecated + default List getResultList() { + return getResultStream().collect(Collectors.toList()); + } + /** + * Returns requested results that match given criteria as a stream. + * @return Stream of events + */ + Stream getResultStream(); } diff --git a/server-spi-private/src/main/java/org/keycloak/events/admin/AdminEventQuery.java b/server-spi-private/src/main/java/org/keycloak/events/admin/AdminEventQuery.java index 5702298190..330130997c 100644 --- a/server-spi-private/src/main/java/org/keycloak/events/admin/AdminEventQuery.java +++ b/server-spi-private/src/main/java/org/keycloak/events/admin/AdminEventQuery.java @@ -19,6 +19,8 @@ package org.keycloak.events.admin; import java.util.Date; import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; /** * @author Stian Thorgersen @@ -127,8 +129,16 @@ public interface AdminEventQuery { /** * Executes the query and returns the results - * - * @return + * @deprecated Use {@link #getResultStream() getResultStream} instead. */ - List getResultList(); + @Deprecated + default List getResultList() { + return getResultStream().collect(Collectors.toList()); + } + + /** + * Executes the query and returns the results as a stream. + * @return Stream of admin events + */ + Stream getResultStream(); } diff --git a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_2_0.java b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_2_0.java index db5c42b5fb..c11822640d 100755 --- a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_2_0.java +++ b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_2_0.java @@ -26,8 +26,6 @@ import org.keycloak.models.RoleModel; import org.keycloak.models.utils.KeycloakModelUtils; import org.keycloak.representations.idm.RealmRepresentation; -import java.util.List; - /** * @author Bill Burke * @version $Revision: 1 $ @@ -68,12 +66,10 @@ public class MigrateTo1_2_0 implements Migration { } public void migrate(KeycloakSession session) { - List realms = session.realms().getRealms(); - for (RealmModel realm : realms) { + session.realms().getRealmsStream().forEach(realm -> { setupBrokerService(realm); setupClientNames(realm); - } - + }); } @Override diff --git a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_3_0.java b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_3_0.java index 85dbad4ccf..b98f25b460 100755 --- a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_3_0.java +++ b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_3_0.java @@ -19,7 +19,6 @@ package org.keycloak.migration.migrators; import org.keycloak.common.util.MultivaluedHashMap; import org.keycloak.component.ComponentFactory; -import org.keycloak.component.ComponentModel; import org.keycloak.migration.ModelVersion; import org.keycloak.models.KeycloakSession; import org.keycloak.models.LDAPConstants; @@ -44,11 +43,7 @@ public class MigrateTo1_3_0 implements Migration { } public void migrate(KeycloakSession session) { - List realms = session.realms().getRealms(); - for (RealmModel realm : realms) { - migrateLDAPProviders(session, realm); - } - + session.realms().getRealmsStream().forEach(realm -> migrateLDAPProviders(session, realm)); } @Override @@ -57,9 +52,7 @@ public class MigrateTo1_3_0 implements Migration { } private void migrateLDAPProviders(KeycloakSession session, RealmModel realm) { - List federationProviders = realm.getUserStorageProviders(); - for (UserStorageProviderModel fedProvider : federationProviders) { - + realm.getUserStorageProvidersStream().forEachOrdered(fedProvider -> { if (fedProvider.getProviderId().equals(LDAPConstants.LDAP_PROVIDER)) { fedProvider = new UserStorageProviderModel(fedProvider); // copy don't want to muck with cache MultivaluedHashMap config = fedProvider.getConfig(); @@ -91,14 +84,13 @@ public class MigrateTo1_3_0 implements Migration { realm.updateComponent(fedProvider); // Create default mappers for LDAP - List mappers = realm.getComponents(fedProvider.getId()); - if (mappers.isEmpty()) { + if (realm.getComponentsStream(fedProvider.getId()).count() == 0) { ProviderFactory ldapFactory = session.getKeycloakSessionFactory().getProviderFactory(UserStorageProvider.class, LDAPConstants.LDAP_PROVIDER); if (ldapFactory != null) { ((ComponentFactory) ldapFactory).onCreate(session, realm, fedProvider); } } } - } + }); } } diff --git a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_4_0.java b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_4_0.java index 792a151680..91783ff978 100755 --- a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_4_0.java +++ b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_4_0.java @@ -29,10 +29,10 @@ import org.keycloak.models.utils.DefaultAuthenticationFlows; import org.keycloak.models.utils.DefaultRequiredActions; import org.keycloak.models.utils.KeycloakModelUtils; import org.keycloak.representations.idm.RealmRepresentation; -import org.keycloak.storage.UserStorageProviderModel; import java.util.Arrays; import java.util.List; +import java.util.Objects; /** * @author Bill Burke @@ -45,15 +45,11 @@ public class MigrateTo1_4_0 implements Migration { } public void migrate(KeycloakSession session) { - List realms = session.realms().getRealms(); - for (RealmModel realm : realms) { - migrateRealm(session, realm); - } - + session.realms().getRealmsStream().forEach(realm -> migrateRealm(session, realm)); } protected void migrateRealm(KeycloakSession session, RealmModel realm) { - if (realm.getAuthenticationFlows().size() == 0) { + if (realm.getAuthenticationFlowsStream().count() == 0) { DefaultAuthenticationFlows.migrateFlows(realm); DefaultRequiredActions.addActions(realm); } @@ -71,19 +67,15 @@ public class MigrateTo1_4_0 implements Migration { private void migrateLDAPMappers(KeycloakSession session, RealmModel realm) { List mandatoryInLdap = Arrays.asList("username", "username-cn", "first name", "last name"); - for (UserStorageProviderModel providerModel : realm.getUserStorageProviders()) { - if (providerModel.getProviderId().equals(LDAPConstants.LDAP_PROVIDER)) { - List mappers = realm.getComponents(providerModel.getId()); - for (ComponentModel mapper : mappers) { - if (mandatoryInLdap.contains(mapper.getName())) { - mapper = new ComponentModel(mapper); // don't want to modify cache - mapper.getConfig().putSingle("is.mandatory.in.ldap", "true"); - realm.updateComponent(mapper); - } - - } - } - } + realm.getUserStorageProvidersStream() + .filter(providerModel -> Objects.equals(providerModel.getProviderId(), LDAPConstants.LDAP_PROVIDER)) + .forEachOrdered(providerModel -> realm.getComponentsStream(providerModel.getId()) + .filter(mapper -> mandatoryInLdap.contains(mapper.getName())) + .forEach(mapper -> { + mapper = new ComponentModel(mapper); // don't want to modify cache + mapper.getConfig().putSingle("is.mandatory.in.ldap", "true"); + realm.updateComponent(mapper); + })); } private void migrateUsers(KeycloakSession session, RealmModel realm) { diff --git a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_5_0.java b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_5_0.java index 8ccb3ef458..26e43431ca 100755 --- a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_5_0.java +++ b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_5_0.java @@ -25,8 +25,6 @@ import org.keycloak.models.RealmModel; import org.keycloak.models.utils.DefaultAuthenticationFlows; import org.keycloak.representations.idm.RealmRepresentation; -import java.util.List; - /** * @author Bill Burke * @version $Revision: 1 $ @@ -39,11 +37,7 @@ public class MigrateTo1_5_0 implements Migration { } public void migrate(KeycloakSession session) { - List realms = session.realms().getRealms(); - for (RealmModel realm : realms) { - migrateRealm(session, realm); - } - + session.realms().getRealmsStream().forEach(realm -> migrateRealm(session, realm)); } @Override diff --git a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_6_0.java b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_6_0.java index d66bfc1896..92f5715bed 100644 --- a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_6_0.java +++ b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_6_0.java @@ -29,8 +29,6 @@ import org.keycloak.models.RoleModel; import org.keycloak.models.utils.KeycloakModelUtils; import org.keycloak.representations.idm.RealmRepresentation; -import java.util.List; - /** * @author Marek Posolda */ @@ -51,10 +49,7 @@ public class MigrateTo1_6_0 implements Migration { throw new RuntimeException("Can't find default locale mapper"); } - List realms = session.realms().getRealms(); - for (RealmModel realm : realms) { - migrateRealm(session, localeMapper, realm); - } + session.realms().getRealmsStream().forEach(realm -> migrateRealm(session, localeMapper, realm)); } @Override diff --git a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_7_0.java b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_7_0.java index adb6801f24..5d56897a84 100644 --- a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_7_0.java +++ b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_7_0.java @@ -21,14 +21,11 @@ import org.keycloak.migration.MigrationProvider; import org.keycloak.migration.ModelVersion; import org.keycloak.models.AuthenticationFlowModel; import org.keycloak.models.Constants; -import org.keycloak.models.IdentityProviderModel; import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; import org.keycloak.models.utils.DefaultAuthenticationFlows; import org.keycloak.representations.idm.RealmRepresentation; -import java.util.List; - /** * @author Marek Posolda */ @@ -41,11 +38,7 @@ public class MigrateTo1_7_0 implements Migration { } public void migrate(KeycloakSession session) { - List realms = session.realms().getRealms(); - for (RealmModel realm : realms) { - migrateRealm(session, realm); - - } + session.realms().getRealmsStream().forEach(realm -> migrateRealm(session, realm)); } @Override @@ -65,12 +58,11 @@ public class MigrateTo1_7_0 implements Migration { DefaultAuthenticationFlows.migrateFlows(realm); AuthenticationFlowModel firstBrokerLoginFlow = realm.getFlowByAlias(DefaultAuthenticationFlows.FIRST_BROKER_LOGIN_FLOW); - List identityProviders = realm.getIdentityProviders(); - for (IdentityProviderModel identityProvider : identityProviders) { - if (identityProvider.getFirstBrokerLoginFlowId() == null) { - identityProvider.setFirstBrokerLoginFlowId(firstBrokerLoginFlow.getId()); - realm.updateIdentityProvider(identityProvider); - } - } + realm.getIdentityProvidersStream() + .filter(provider -> provider.getFirstBrokerLoginFlowId() == null) + .forEach(provider -> { + provider.setFirstBrokerLoginFlowId(firstBrokerLoginFlow.getId()); + realm.updateIdentityProvider(provider); + }); } } diff --git a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_8_0.java b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_8_0.java index f28bb5479b..231e57f84c 100644 --- a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_8_0.java +++ b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_8_0.java @@ -26,7 +26,7 @@ import org.keycloak.models.utils.KeycloakModelUtils; import org.keycloak.representations.idm.RealmRepresentation; import org.keycloak.storage.UserStorageProviderModel; -import java.util.List; +import java.util.Objects; /** * @author Marek Posolda @@ -41,12 +41,7 @@ public class MigrateTo1_8_0 implements Migration { public void migrate(KeycloakSession session) { - List realms = session.realms().getRealms(); - for (RealmModel realm : realms) { - - migrateRealm(realm); - - } + session.realms().getRealmsStream().forEach(this::migrateRealm); } @Override @@ -55,30 +50,22 @@ public class MigrateTo1_8_0 implements Migration { } protected void migrateRealm(RealmModel realm) { - List federationProviders = realm.getUserStorageProviders(); - for (UserStorageProviderModel fedProvider : federationProviders) { - - if (fedProvider.getProviderId().equals(LDAPConstants.LDAP_PROVIDER)) { - - if (isActiveDirectory(fedProvider)) { - // Create mapper for MSAD account controls - if (getMapperByName(realm, fedProvider, "MSAD account controls") == null) { - ComponentModel mapperModel = KeycloakModelUtils.createComponentModel("MSAD account controls", fedProvider.getId(), LDAPConstants.MSAD_USER_ACCOUNT_CONTROL_MAPPER, "org.keycloak.storage.ldap.mappers.LDAPStorageMapper"); - realm.addComponentModel(mapperModel); - } - } - } - } + realm.getUserStorageProvidersStream() + .filter(fedProvider -> Objects.equals(fedProvider.getProviderId(), LDAPConstants.LDAP_PROVIDER)) + .filter(this::isActiveDirectory) + .filter(fedProvider -> Objects.isNull(getMapperByName(realm, fedProvider, "MSAD account controls"))) + // Create mapper for MSAD account controls + .map(fedProvider -> KeycloakModelUtils.createComponentModel("MSAD account controls", + fedProvider.getId(), LDAPConstants.MSAD_USER_ACCOUNT_CONTROL_MAPPER, + "org.keycloak.storage.ldap.mappers.LDAPStorageMapper")) + .forEachOrdered(realm::addComponentModel); } public static ComponentModel getMapperByName(RealmModel realm, ComponentModel providerModel, String name) { - List components = realm.getComponents(providerModel.getId(), "org.keycloak.storage.ldap.mappers.LDAPStorageMapper"); - for (ComponentModel component : components) { - if (component.getName().equals(name)) { - return component; - } - } - return null; + return realm.getComponentsStream(providerModel.getId(), "org.keycloak.storage.ldap.mappers.LDAPStorageMapper") + .filter(component -> Objects.equals(component.getName(), name)) + .findFirst() + .orElse(null); } diff --git a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_9_2.java b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_9_2.java index 171d9ef0e5..97d831a558 100644 --- a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_9_2.java +++ b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_9_2.java @@ -35,9 +35,7 @@ public class MigrateTo1_9_2 implements Migration { } public void migrate(KeycloakSession session) { - for (RealmModel realm : session.realms().getRealms()) { - migrateRealm(realm); - } + session.realms().getRealmsStream().forEach(this::migrateRealm); } @Override diff --git a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo2_0_0.java b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo2_0_0.java index 788e373a7c..b85eee8ac2 100644 --- a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo2_0_0.java +++ b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo2_0_0.java @@ -33,9 +33,7 @@ public class MigrateTo2_0_0 implements Migration { } public void migrate(KeycloakSession session) { - for (RealmModel realm : session.realms().getRealms()) { - migrateAuthorizationServices(realm); - } + session.realms().getRealmsStream().forEach(this::migrateAuthorizationServices); } @Override diff --git a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo2_1_0.java b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo2_1_0.java index 550dac4ccf..6eef89a99e 100644 --- a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo2_1_0.java +++ b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo2_1_0.java @@ -47,10 +47,10 @@ public class MigrateTo2_1_0 implements Migration { } public void migrate(KeycloakSession session) { - for (RealmModel realm : session.realms().getRealms()) { + session.realms().getRealmsStream().forEach(realm -> { migrateDefaultRequiredAction(realm); migrateRolePolicies(realm, session); - } + }); } @Override diff --git a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo2_2_0.java b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo2_2_0.java index 19ab4c4a1c..762c7c9641 100644 --- a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo2_2_0.java +++ b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo2_2_0.java @@ -35,9 +35,7 @@ public class MigrateTo2_2_0 implements Migration { } public void migrate(KeycloakSession session) { - for (RealmModel realm : session.realms().getRealms()) { - addIdentityProviderAuthenticator(realm); - } + session.realms().getRealmsStream().forEach(this::addIdentityProviderAuthenticator); } @Override @@ -47,13 +45,12 @@ public class MigrateTo2_2_0 implements Migration { } private void addIdentityProviderAuthenticator(RealmModel realm) { - String defaultProvider = null; - for (IdentityProviderModel provider : realm.getIdentityProviders()) { - if (provider.isEnabled() && provider.isAuthenticateByDefault()) { - defaultProvider = provider.getAlias(); - break; - } - } + String defaultProvider = realm.getIdentityProvidersStream() + .filter(IdentityProviderModel::isEnabled) + .filter(IdentityProviderModel::isAuthenticateByDefault) + .map(IdentityProviderModel::getAlias) + .findFirst() + .orElse(null); DefaultAuthenticationFlows.addIdentityProviderAuthenticator(realm, defaultProvider); } diff --git a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo2_3_0.java b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo2_3_0.java index a2e8c1a149..d147eb2c99 100644 --- a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo2_3_0.java +++ b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo2_3_0.java @@ -19,7 +19,6 @@ package org.keycloak.migration.migrators; import org.keycloak.migration.ModelVersion; -import org.keycloak.models.ClientScopeModel; import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; import org.keycloak.representations.idm.RealmRepresentation; @@ -33,17 +32,13 @@ public class MigrateTo2_3_0 implements Migration { @Override public void migrate(KeycloakSession session) { - for (RealmModel realm : session.realms().getRealms()) { - migrateRealm(realm); - } + session.realms().getRealmsStream().forEach(this::migrateRealm); } protected void migrateRealm(RealmModel realm) { realm.getClientsStream().forEach(MigrationUtils::updateProtocolMappers); - for (ClientScopeModel clientScope : realm.getClientScopes()) { - MigrationUtils.updateProtocolMappers(clientScope); - } + realm.getClientScopesStream().forEach(MigrationUtils::updateProtocolMappers); } @Override diff --git a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo2_5_0.java b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo2_5_0.java index b28264f22f..7744836d27 100644 --- a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo2_5_0.java +++ b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo2_5_0.java @@ -33,9 +33,7 @@ public class MigrateTo2_5_0 implements Migration { @Override public void migrate(KeycloakSession session) { - session.realms().getRealms().stream().forEach( - r -> DefaultKeyProviders.createSecretProvider(r) - ); + session.realms().getRealmsStream().forEach(DefaultKeyProviders::createSecretProvider); } @Override diff --git a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo3_0_0.java b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo3_0_0.java index 2e8eb3d94a..4a465a0dbd 100644 --- a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo3_0_0.java +++ b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo3_0_0.java @@ -41,12 +41,7 @@ public class MigrateTo3_0_0 implements Migration { @Override public void migrate(KeycloakSession session) { - for (RealmModel realm : session.realms().getRealms()) { - - migrateRealm(realm); - - } - + session.realms().getRealmsStream().forEach(this::migrateRealm); } @Override diff --git a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo3_1_0.java b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo3_1_0.java index 4f66fc07df..e5bf948def 100644 --- a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo3_1_0.java +++ b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo3_1_0.java @@ -36,9 +36,7 @@ public class MigrateTo3_1_0 implements Migration { @Override public void migrate(KeycloakSession session) { - for (RealmModel realm : session.realms().getRealms()) { - migrateRealm(realm); - } + session.realms().getRealmsStream().forEach(this::migrateRealm); } protected void migrateRealm(RealmModel realm) { diff --git a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo3_2_0.java b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo3_2_0.java index 13d77e3b35..ef9abc4160 100644 --- a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo3_2_0.java +++ b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo3_2_0.java @@ -33,10 +33,7 @@ public class MigrateTo3_2_0 implements Migration { @Override public void migrate(KeycloakSession session) { - for (RealmModel realm : session.realms().getRealms()) { - migrateRealm(session, realm); - - } + session.realms().getRealmsStream().forEach(realm -> migrateRealm(session, realm)); } @Override diff --git a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo3_4_0.java b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo3_4_0.java index 8e6c13316c..6accd3d889 100644 --- a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo3_4_0.java +++ b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo3_4_0.java @@ -17,7 +17,6 @@ package org.keycloak.migration.migrators; -import org.keycloak.keys.KeyProvider; import org.keycloak.migration.ModelVersion; import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; @@ -37,11 +36,7 @@ public class MigrateTo3_4_0 implements Migration { @Override public void migrate(KeycloakSession session) { - session.realms().getRealms().stream().forEach( - r -> { - migrateRealm(r); - } - ); + session.realms().getRealmsStream().forEach(this::migrateRealm); } @Override diff --git a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo3_4_1.java b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo3_4_1.java index c855643b2f..7afd9c3206 100644 --- a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo3_4_1.java +++ b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo3_4_1.java @@ -37,11 +37,7 @@ public class MigrateTo3_4_1 implements Migration { @Override public void migrate(KeycloakSession session) { - session.realms().getRealms().stream().forEach( - r -> { - migrateRealm(r); - } - ); + session.realms().getRealmsStream().forEach(this::migrateRealm); } @Override diff --git a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo3_4_2.java b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo3_4_2.java index 9edf276322..669505b8b8 100644 --- a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo3_4_2.java +++ b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo3_4_2.java @@ -36,11 +36,7 @@ public class MigrateTo3_4_2 implements Migration { @Override public void migrate(KeycloakSession session) { - session.realms().getRealms().stream().forEach( - r -> { - migrateRealm(r); - } - ); + session.realms().getRealmsStream().forEach(this::migrateRealm); } @Override diff --git a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo4_0_0.java b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo4_0_0.java index 96e0a440a1..ac9cdae41d 100644 --- a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo4_0_0.java +++ b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo4_0_0.java @@ -18,10 +18,10 @@ package org.keycloak.migration.migrators; import java.util.List; +import java.util.Objects; import org.jboss.logging.Logger; import org.keycloak.OAuth2Constants; -import org.keycloak.component.ComponentModel; import org.keycloak.migration.ModelVersion; import org.keycloak.models.ClientModel; import org.keycloak.models.ClientScopeModel; @@ -48,11 +48,7 @@ public class MigrateTo4_0_0 implements Migration { @Override public void migrate(KeycloakSession session) { - session.realms().getRealms().stream().forEach( - r -> { - migrateRealm(session, r, false); - } - ); + session.realms().getRealmsStream().forEach(realm -> migrateRealm(session, realm, false)); } @Override @@ -63,13 +59,14 @@ public class MigrateTo4_0_0 implements Migration { protected void migrateRealm(KeycloakSession session, RealmModel realm, boolean json) { // Upgrade names of clientScopes to not contain space - for (ClientScopeModel clientScope : realm.getClientScopes()) { - if (clientScope.getName().contains(" ")) { - LOG.debugf("Replacing spaces with underscores in the name of client scope '%s' of realm '%s'", clientScope.getName(), realm.getName()); - String replacedName = clientScope.getName().replaceAll(" ", "_"); - clientScope.setName(replacedName); - } - } + realm.getClientScopesStream() + .filter(clientScope -> clientScope.getName().contains(" ")) + .forEach(clientScope -> { + LOG.debugf("Replacing spaces with underscores in the name of client scope '%s' of realm '%s'", + clientScope.getName(), realm.getName()); + String replacedName = clientScope.getName().replaceAll(" ", "_"); + clientScope.setName(replacedName); + }); if (!json) { // Add default client scopes. But don't add them to existing clients. For JSON, they were already added @@ -78,17 +75,17 @@ public class MigrateTo4_0_0 implements Migration { } // Upgrade configuration of "allowed-client-templates" client registration policy - for (ComponentModel component : realm.getComponents(realm.getId(), "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy")) { - if ("allowed-client-templates".equals(component.getProviderId())) { - List configVal = component.getConfig().remove("allowed-client-templates"); - if (configVal != null) { - component.getConfig().put("allowed-client-scopes", configVal); - } - component.put("allow-default-scopes", true); + realm.getComponentsStream(realm.getId(), "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy") + .filter(component -> Objects.equals(component.getProviderId(), "allowed-client-templates")) + .forEach(component -> { + List configVal = component.getConfig().remove("allowed-client-templates"); + if (configVal != null) { + component.getConfig().put("allowed-client-scopes", configVal); + } + component.put("allow-default-scopes", true); - realm.updateComponent(component); - } - } + realm.updateComponent(component); + }); // If client has scope for offline_access role (either directly or through fullScopeAllowed), then add offline_access client diff --git a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo4_2_0.java b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo4_2_0.java index e14ca50cea..748ee544fc 100644 --- a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo4_2_0.java +++ b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo4_2_0.java @@ -19,8 +19,7 @@ package org.keycloak.migration.migrators; import static java.util.Comparator.comparing; -import java.util.List; -import java.util.stream.Collectors; +import java.util.concurrent.atomic.AtomicInteger; import org.jboss.logging.Logger; import org.keycloak.migration.ModelVersion; @@ -45,29 +44,27 @@ public class MigrateTo4_2_0 implements Migration { @Override public void migrate(KeycloakSession session) { - session.realms().getRealms().stream().forEach(r -> { - migrateRealm(session, r, false); - }); + session.realms().getRealmsStream().forEach(this::migrateRealm); } @Override public void migrateImport(KeycloakSession session, RealmModel realm, RealmRepresentation rep, boolean skipUserDependent) { - migrateRealm(session, realm, true); + migrateRealm(realm); } - protected void migrateRealm(KeycloakSession session, RealmModel realm, boolean json) { + protected void migrateRealm(RealmModel realm) { // Set default priority of required actions in alphabetical order - List actions = realm.getRequiredActionProviders().stream() - .sorted(comparing(RequiredActionProviderModel::getName)).collect(Collectors.toList()); - int priority = 10; - for (RequiredActionProviderModel model : actions) { - LOG.debugf("Setting priority '%d' for required action '%s' in realm '%s'", priority, model.getAlias(), - realm.getName()); - model.setPriority(priority); - priority += 10; + AtomicInteger priority = new AtomicInteger(10); + realm.getRequiredActionProvidersStream() + .sorted(comparing(RequiredActionProviderModel::getName)) + .forEachOrdered(model -> { + LOG.debugf("Setting priority '%d' for required action '%s' in realm '%s'", priority.get(), model.getAlias(), + realm.getName()); + model.setPriority(priority.get()); + priority.addAndGet(10); - // Save - realm.updateRequiredActionProvider(model); - } + // Save + realm.updateRequiredActionProvider(model); + }); } } diff --git a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo4_6_0.java b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo4_6_0.java index 1891cf68c2..0293d94378 100644 --- a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo4_6_0.java +++ b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo4_6_0.java @@ -42,9 +42,7 @@ public class MigrateTo4_6_0 implements Migration { @Override public void migrate(KeycloakSession session) { - session.realms().getRealms().stream().forEach(r -> { - migrateRealm(session, r, false); - }); + session.realms().getRealmsStream().forEach(realm -> migrateRealm(session, realm, false)); } @Override diff --git a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo6_0_0.java b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo6_0_0.java index d04780ba95..600345d8ae 100644 --- a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo6_0_0.java +++ b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo6_0_0.java @@ -43,9 +43,7 @@ public class MigrateTo6_0_0 implements Migration { @Override public void migrate(KeycloakSession session) { - session.realms().getRealms().stream().forEach(r -> { - migrateRealm(session, r, false); - }); + session.realms().getRealmsStream().forEach(realm -> migrateRealm(session, realm, false)); } @Override diff --git a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo8_0_0.java b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo8_0_0.java index 2d6d8541f6..b38b10d22a 100644 --- a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo8_0_0.java +++ b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo8_0_0.java @@ -46,11 +46,9 @@ public class MigrateTo8_0_0 implements Migration { @Override public void migrate(KeycloakSession session) { // Perform basic realm migration first (non multi-factor authentication) - session.realms().getRealms().stream().forEach(realm -> migrateRealmCommon(realm)); + session.realms().getRealmsStream().forEach(this::migrateRealmCommon); // Moreover, for multi-factor authentication migrate optional execution of realm flows to subflows - session.realms().getRealms().stream().forEach(r -> { - migrateRealmMFA(session, r, false); - }); + session.realms().getRealmsStream().forEach(realm -> migrateRealmMFA(realm)); } @Override @@ -79,15 +77,12 @@ public class MigrateTo8_0_0 implements Migration { } } - protected void migrateRealmMFA(KeycloakSession session, RealmModel realm, boolean jsn) { - for (AuthenticationFlowModel authFlow : realm.getAuthenticationFlows()) { - for (AuthenticationExecutionModel authExecution : realm.getAuthenticationExecutions(authFlow.getId())) { - // Those were OPTIONAL executions in previous version - if (authExecution.getRequirement() == AuthenticationExecutionModel.Requirement.CONDITIONAL) { - migrateOptionalAuthenticationExecution(realm, authFlow, authExecution, true); - } - } - } + protected void migrateRealmMFA(RealmModel realm) { + realm.getAuthenticationFlowsStream() + .forEach(authFlow -> + realm.getAuthenticationExecutionsStream(authFlow.getId()) + .filter(exe -> exe.getRequirement() == AuthenticationExecutionModel.Requirement.CONDITIONAL) + .forEachOrdered(exe -> migrateOptionalAuthenticationExecution(realm, authFlow, exe, true))); } public static void migrateOptionalAuthenticationExecution(RealmModel realm, AuthenticationFlowModel parentFlow, AuthenticationExecutionModel optionalExecution, boolean updateOptionalExecution) { diff --git a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo8_0_2.java b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo8_0_2.java index 1ee95b3aad..675dbe17ce 100644 --- a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo8_0_2.java +++ b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo8_0_2.java @@ -19,6 +19,10 @@ package org.keycloak.migration.migrators; import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; import org.jboss.logging.Logger; import org.keycloak.migration.ModelVersion; @@ -28,6 +32,8 @@ import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; import org.keycloak.representations.idm.RealmRepresentation; +import static org.keycloak.models.AuthenticationExecutionModel.Requirement.*; + /** * @author Marek Posolda */ @@ -44,7 +50,7 @@ public class MigrateTo8_0_2 implements Migration { @Override public void migrate(KeycloakSession session) { - session.realms().getRealms().forEach(this::migrateAuthenticationFlowsWithAlternativeRequirements); + session.realms().getRealmsStream().forEach(this::migrateAuthenticationFlowsWithAlternativeRequirements); } @Override @@ -54,47 +60,39 @@ public class MigrateTo8_0_2 implements Migration { protected void migrateAuthenticationFlowsWithAlternativeRequirements(RealmModel realm) { - for (AuthenticationFlowModel flow : realm.getAuthenticationFlows()) { + for (AuthenticationFlowModel flow : realm.getAuthenticationFlowsStream().collect(Collectors.toList())) { + List executions = realm.getAuthenticationExecutionsStream(flow.getId()) + .collect(Collectors.toList()); - boolean alternativeFound = false; - boolean requiredFound = false; - for (AuthenticationExecutionModel execution : realm.getAuthenticationExecutions(flow.getId())) { - switch (execution.getRequirement()) { - case REQUIRED: - case CONDITIONAL: - requiredFound = true; - break; - case ALTERNATIVE: - alternativeFound = true; - break; - } - } + Set requirements = executions.stream() + .map(AuthenticationExecutionModel::getRequirement) + .collect(Collectors.toSet()); // This flow contains some REQUIRED and ALTERNATIVE at the same level. We will migrate ALTERNATIVES to separate subflows // to try to preserve same behaviour as in previous versions - if (requiredFound && alternativeFound) { + if (requirements.contains(REQUIRED) || requirements.contains(CONDITIONAL) && requirements.contains(ALTERNATIVE)) { // Suffix used just to avoid name conflicts - int suffix = 0; + AtomicInteger suffix = new AtomicInteger(0); LinkedList alternativesToMigrate = new LinkedList<>(); - for (AuthenticationExecutionModel execution : realm.getAuthenticationExecutions(flow.getId())) { + for (AuthenticationExecutionModel execution: executions) { if (AuthenticationExecutionModel.Requirement.ALTERNATIVE.equals(execution.getRequirement())) { alternativesToMigrate.add(execution); } // If we have some REQUIRED then ALTERNATIVE and then REQUIRED/CONDITIONAL, we migrate the alternatives to the new subflow. - if (AuthenticationExecutionModel.Requirement.REQUIRED.equals(execution.getRequirement()) || - AuthenticationExecutionModel.Requirement.CONDITIONAL.equals(execution.getRequirement())) { + if (REQUIRED.equals(execution.getRequirement()) || + CONDITIONAL.equals(execution.getRequirement())) { if (!alternativesToMigrate.isEmpty()) { - migrateAlternatives(realm, flow, alternativesToMigrate, suffix); - suffix += 1; + migrateAlternatives(realm, flow, alternativesToMigrate, suffix.get()); + suffix.addAndGet(1); alternativesToMigrate.clear(); } } } if (!alternativesToMigrate.isEmpty()) { - migrateAlternatives(realm, flow, alternativesToMigrate, suffix); + migrateAlternatives(realm, flow, alternativesToMigrate, suffix.get()); } } } @@ -116,7 +114,7 @@ public class MigrateTo8_0_2 implements Migration { AuthenticationExecutionModel execution = new AuthenticationExecutionModel(); execution.setParentFlow(parentFlow.getId()); - execution.setRequirement(AuthenticationExecutionModel.Requirement.REQUIRED); + execution.setRequirement(REQUIRED); execution.setFlowId(newFlow.getId()); // Use same priority as the first ALTERNATIVE as new execution will defacto replace it in the parent flow execution.setPriority(alternativesToMigrate.getFirst().getPriority()); diff --git a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo9_0_0.java b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo9_0_0.java index e61b39ad11..e2b4d0aad0 100644 --- a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo9_0_0.java +++ b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo9_0_0.java @@ -47,7 +47,7 @@ public class MigrateTo9_0_0 implements Migration { @Override public void migrate(KeycloakSession session) { - session.realms().getRealms().stream().forEach(realm -> migrateRealmCommon(realm)); + session.realms().getRealmsStream().forEach(this::migrateRealmCommon); } @Override diff --git a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo9_0_4.java b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo9_0_4.java index a1e63628e8..a59f98fb15 100644 --- a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo9_0_4.java +++ b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo9_0_4.java @@ -38,7 +38,7 @@ public class MigrateTo9_0_4 implements Migration { @Override public void migrate(KeycloakSession session) { - session.realms().getRealms().stream().forEach(this::checkAuthConfigNullAlias); + session.realms().getRealmsStream().forEach(this::checkAuthConfigNullAlias); } @Override @@ -46,7 +46,7 @@ public class MigrateTo9_0_4 implements Migration { } protected void checkAuthConfigNullAlias(RealmModel realm) { - realm.getAuthenticatorConfigs().stream() + realm.getAuthenticatorConfigsStream() .filter(this::hasNullAlias) .forEach((config) -> this.setRandomAlias(realm, config)); } diff --git a/server-spi-private/src/main/java/org/keycloak/models/utils/DefaultAuthenticationFlows.java b/server-spi-private/src/main/java/org/keycloak/models/utils/DefaultAuthenticationFlows.java index c39f29b122..815911f966 100755 --- a/server-spi-private/src/main/java/org/keycloak/models/utils/DefaultAuthenticationFlows.java +++ b/server-spi-private/src/main/java/org/keycloak/models/utils/DefaultAuthenticationFlows.java @@ -24,10 +24,7 @@ import org.keycloak.models.RealmModel; import org.keycloak.models.RequiredCredentialModel; import org.keycloak.representations.idm.IdentityProviderRepresentation; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; +import java.util.*; /** * @author Bill Burke @@ -150,13 +147,7 @@ public class DefaultAuthenticationFlows { } private static boolean hasCredentialType(RealmModel realm, String type) { - for (RequiredCredentialModel requiredCredentialModel : realm.getRequiredCredentials()) { - if (type.equals(requiredCredentialModel.getType())) { - return true; - } - - } - return false; + return realm.getRequiredCredentialsStream().anyMatch(r -> Objects.equals(r.getType(), type)); } public static void resetCredentialsFlow(RealmModel realm) { @@ -388,20 +379,16 @@ public class DefaultAuthenticationFlows { } public static void addIdentityProviderAuthenticator(RealmModel realm, String defaultProvider) { - String browserFlowId = null; - for (AuthenticationFlowModel f : realm.getAuthenticationFlows()) { - if (f.getAlias().equals(DefaultAuthenticationFlows.BROWSER_FLOW)) { - browserFlowId = f.getId(); - break; - } - } + String browserFlowId = realm.getAuthenticationFlowsStream() + .filter(f -> Objects.equals(f.getAlias(), DefaultAuthenticationFlows.BROWSER_FLOW)) + .map(AuthenticationFlowModel::getId) + .findFirst() + .orElse(null); if (browserFlowId != null) { - for (AuthenticationExecutionModel e : realm.getAuthenticationExecutions(browserFlowId)) { - if ("identity-provider-redirector".equals(e.getAuthenticator())) { - return; - } - } + if (realm.getAuthenticationExecutionsStream(browserFlowId) + .anyMatch(e -> Objects.equals(e.getAuthenticator(), "identity-provider-redirector"))) + return; AuthenticationExecutionModel execution; execution = new AuthenticationExecutionModel(); @@ -618,7 +605,8 @@ public class DefaultAuthenticationFlows { KeycloakModelUtils.deepFindAuthenticationExecutions(realm, browserFlow, browserExecutions); for (AuthenticationExecutionModel browserExecution : browserExecutions) { if (browserExecution.isAuthenticatorFlow()){ - if (realm.getAuthenticationExecutions(browserExecution.getFlowId()).stream().anyMatch(e -> e.getAuthenticator().equals("auth-otp-form"))){ + if (realm.getAuthenticationExecutionsStream(browserExecution.getFlowId()) + .anyMatch(e -> e.getAuthenticator().equals("auth-otp-form"))){ execution.setRequirement(browserExecution.getRequirement()); } } diff --git a/server-spi-private/src/main/java/org/keycloak/models/utils/DefaultKeyProviders.java b/server-spi-private/src/main/java/org/keycloak/models/utils/DefaultKeyProviders.java index 440729fbc4..ea95874730 100644 --- a/server-spi-private/src/main/java/org/keycloak/models/utils/DefaultKeyProviders.java +++ b/server-spi-private/src/main/java/org/keycloak/models/utils/DefaultKeyProviders.java @@ -23,7 +23,7 @@ import org.keycloak.crypto.Algorithm; import org.keycloak.keys.KeyProvider; import org.keycloak.models.RealmModel; -import java.util.List; +import java.util.Objects; /** * @author Stian Thorgersen @@ -81,13 +81,8 @@ public class DefaultKeyProviders { } protected static boolean hasProvider(RealmModel realm, String providerId) { - List currentComponents = realm.getComponents(realm.getId(), KeyProvider.class.getName()); - for (ComponentModel current : currentComponents) { - if (current.getProviderId().equals(providerId)) { - return true; - } - } - return false; + return realm.getComponentsStream(realm.getId(), KeyProvider.class.getName()) + .anyMatch(component -> Objects.equals(component.getProviderId(), providerId)); } public static void createProviders(RealmModel realm, String privateKeyPem, String certificatePem) { diff --git a/server-spi-private/src/main/java/org/keycloak/models/utils/KeycloakModelUtils.java b/server-spi-private/src/main/java/org/keycloak/models/utils/KeycloakModelUtils.java index d2bb0a9540..3247ef4f02 100755 --- a/server-spi-private/src/main/java/org/keycloak/models/utils/KeycloakModelUtils.java +++ b/server-spi-private/src/main/java/org/keycloak/models/utils/KeycloakModelUtils.java @@ -35,7 +35,6 @@ import org.keycloak.models.KeycloakSessionFactory; import org.keycloak.models.KeycloakSessionTask; import org.keycloak.models.KeycloakTransaction; import org.keycloak.models.RealmModel; -import org.keycloak.models.RoleContainerModel; import org.keycloak.models.RoleModel; import org.keycloak.models.ScopeContainerModel; import org.keycloak.models.UserCredentialModel; @@ -296,21 +295,17 @@ public final class KeycloakModelUtils { return null; } - for (UserStorageProviderModel fedProvider : realm.getUserStorageProviders()) { - if (displayName.equals(fedProvider.getName())) { - return fedProvider; - } - } - return null; + return realm.getUserStorageProvidersStream() + .filter(fedProvider -> Objects.equals(fedProvider.getName(), displayName)) + .findFirst() + .orElse(null); } public static UserStorageProviderModel findUserStorageProviderById(String fedProviderId, RealmModel realm) { - for (UserStorageProviderModel fedProvider : realm.getUserStorageProviders()) { - if (fedProviderId.equals(fedProvider.getId())) { - return fedProvider; - } - } - return null; + return realm.getUserStorageProvidersStream() + .filter(fedProvider -> Objects.equals(fedProvider.getId(), fedProviderId)) + .findFirst() + .orElse(null); } public static ComponentModel createComponentModel(String name, String parentId, String providerId, String providerType, String... config) { @@ -364,15 +359,14 @@ public final class KeycloakModelUtils { * @param result input should be empty list. At the end will be all executions added to this list */ public static void deepFindAuthenticationExecutions(RealmModel realm, AuthenticationFlowModel flow, List result) { - List executions = realm.getAuthenticationExecutions(flow.getId()); - for (AuthenticationExecutionModel execution : executions) { + realm.getAuthenticationExecutionsStream(flow.getId()).forEachOrdered(execution -> { if (execution.isAuthenticatorFlow()) { AuthenticationFlowModel subFlow = realm.getAuthenticationFlowById(execution.getFlowId()); deepFindAuthenticationExecutions(realm, subFlow, result); } else { result.add(execution); } - } + }); } public static String resolveFirstAttribute(GroupModel group, String name) { @@ -575,13 +569,9 @@ public final class KeycloakModelUtils { if ((realmFlow = realm.getResetCredentialsFlow()) != null && realmFlow.getId().equals(model.getId())) return true; if ((realmFlow = realm.getDockerAuthenticationFlow()) != null && realmFlow.getId().equals(model.getId())) return true; - for (IdentityProviderModel idp : realm.getIdentityProviders()) { - if (model.getId().equals(idp.getFirstBrokerLoginFlowId())) return true; - if (model.getId().equals(idp.getPostBrokerLoginFlowId())) return true; - } - - return false; - + return realm.getIdentityProvidersStream().anyMatch(idp -> + Objects.equals(idp.getFirstBrokerLoginFlowId(), model.getId()) || + Objects.equals(idp.getPostBrokerLoginFlowId(), model.getId())); } public static boolean isClientScopeUsed(RealmModel realm, ClientScopeModel clientScope) { @@ -592,13 +582,14 @@ public final class KeycloakModelUtils { } public static ClientScopeModel getClientScopeByName(RealmModel realm, String clientScopeName) { - for (ClientScopeModel clientScope : realm.getClientScopes()) { - if (clientScopeName.equals(clientScope.getName())) { - return clientScope; - } - } - // check if we are referencing a client instead of a scope - return realm.getClientsStream().filter(c -> clientScopeName.equals(c.getClientId())).findFirst().orElse(null); + return realm.getClientScopesStream() + .filter(clientScope -> Objects.equals(clientScopeName, clientScope.getName())) + .findFirst() + // check if we are referencing a client instead of a scope + .orElse(realm.getClientsStream() + .filter(c -> Objects.equals(clientScopeName, c.getClientId())) + .findFirst() + .orElse(null)); } /** diff --git a/server-spi-private/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java b/server-spi-private/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java index 54a0666ced..bfa5ff1ca2 100755 --- a/server-spi-private/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java +++ b/server-spi-private/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java @@ -39,8 +39,6 @@ import org.keycloak.representations.idm.authorization.*; import org.keycloak.storage.StorageId; import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; @@ -323,12 +321,10 @@ public class ModelToRepresentation { if (realm.getEventsExpiration() != 0) { rep.setEventsExpiration(realm.getEventsExpiration()); } - if (realm.getEventsListeners() != null) { - rep.setEventsListeners(new LinkedList<>(realm.getEventsListeners())); - } - if (realm.getEnabledEventTypes() != null) { - rep.setEnabledEventTypes(new LinkedList<>(realm.getEnabledEventTypes())); - } + + rep.setEventsListeners(realm.getEventsListenersStream().collect(Collectors.toList())); + + rep.setEnabledEventTypes(realm.getEnabledEventTypesStream().collect(Collectors.toList())); rep.setAdminEventsEnabled(realm.isAdminEventsEnabled()); rep.setAdminEventsDetailsEnabled(realm.isAdminEventsDetailsEnabled()); @@ -419,27 +415,23 @@ public class ModelToRepresentation { rep.setDefaultGroups(defaultGroups); } - List requiredCredentialModels = realm.getRequiredCredentials(); - if (!requiredCredentialModels.isEmpty()) { - rep.setRequiredCredentials(new HashSet<>()); - for (RequiredCredentialModel cred : requiredCredentialModels) { - rep.getRequiredCredentials().add(cred.getType()); - } + Set reqCredentials = realm.getRequiredCredentialsStream() + .map(RequiredCredentialModel::getType) + .collect(Collectors.toSet()); + if (!reqCredentials.isEmpty()) { + rep.setRequiredCredentials(reqCredentials); } - for (IdentityProviderModel provider : realm.getIdentityProviders()) { - rep.addIdentityProvider(toRepresentation(realm, provider)); - } + List identityProviders = realm.getIdentityProvidersStream() + .map(provider -> toRepresentation(realm, provider)).collect(Collectors.toList()); + rep.setIdentityProviders(identityProviders); - for (IdentityProviderMapperModel mapper : realm.getIdentityProviderMappers()) { - rep.addIdentityProviderMapper(toRepresentation(mapper)); - } + List identityProviderMappers = realm.getIdentityProviderMappersStream() + .map(ModelToRepresentation::toRepresentation).collect(Collectors.toList()); + rep.setIdentityProviderMappers(identityProviderMappers); rep.setInternationalizationEnabled(realm.isInternationalizationEnabled()); - if (realm.getSupportedLocales() != null) { - rep.setSupportedLocales(new HashSet<>()); - rep.getSupportedLocales().addAll(realm.getSupportedLocales()); - } + rep.setSupportedLocales(realm.getSupportedLocalesStream().collect(Collectors.toSet())); rep.setDefaultLocale(realm.getDefaultLocale()); if (internal) { exportAuthenticationFlows(realm, rep); @@ -479,47 +471,22 @@ public class ModelToRepresentation { } public static void exportAuthenticationFlows(RealmModel realm, RealmRepresentation rep) { - rep.setAuthenticationFlows(new LinkedList<>()); - rep.setAuthenticatorConfig(new LinkedList<>()); - - List authenticationFlows = new ArrayList<>(realm.getAuthenticationFlows()); - //ensure consistent ordering of authenticationFlows. - Collections.sort(authenticationFlows, new Comparator() { - @Override - public int compare(AuthenticationFlowModel left, AuthenticationFlowModel right) { - String l = left.getAlias() != null ? left.getAlias() : "\0"; - String r = right.getAlias() != null ? right.getAlias() : "\0"; - return l.compareTo(r); - } - }); - - for (AuthenticationFlowModel model : authenticationFlows) { - AuthenticationFlowRepresentation flowRep = toRepresentation(realm, model); - rep.getAuthenticationFlows().add(flowRep); - } - - List authenticatorConfigs = new ArrayList<>(realm.getAuthenticatorConfigs()); - //ensure consistent ordering of authenticatorConfigs. - Collections.sort(authenticatorConfigs, new Comparator() { - @Override - public int compare(AuthenticatorConfigModel left, AuthenticatorConfigModel right) { - String l = left.getAlias() != null ? left.getAlias() : "\0"; - String r = right.getAlias() != null ? right.getAlias() : "\0"; - return l.compareTo(r); - } - }); - - for (AuthenticatorConfigModel model : authenticatorConfigs) { - rep.getAuthenticatorConfig().add(toRepresentation(model)); - } + List authenticationFlows = realm.getAuthenticationFlowsStream() + .sorted(AuthenticationFlowModel.AuthenticationFlowComparator.SINGLETON) + .map(flow -> toRepresentation(realm, flow)) + .collect(Collectors.toList()); + rep.setAuthenticationFlows(authenticationFlows); + List authenticationConfigs = realm.getAuthenticatorConfigsStream() + .sorted(AuthenticatorConfigModel.AuthenticationConfigComparator.SINGLETON) + .map(ModelToRepresentation::toRepresentation) + .collect(Collectors.toList()); + rep.setAuthenticatorConfig(authenticationConfigs); } public static void exportRequiredActions(RealmModel realm, RealmRepresentation rep) { - - rep.setRequiredActions(new LinkedList<>()); - - realm.getRequiredActionProviders().forEach(action -> rep.getRequiredActions().add(toRepresentation(action))); + rep.setRequiredActions(realm.getRequiredActionProvidersStream() + .map(ModelToRepresentation::toRepresentation).collect(Collectors.toList())); } public static RealmEventsConfigRepresentation toEventsConfigReprensetation(RealmModel realm) { @@ -530,13 +497,9 @@ public class ModelToRepresentation { rep.setEventsExpiration(realm.getEventsExpiration()); } - if (realm.getEventsListeners() != null) { - rep.setEventsListeners(new LinkedList<>(realm.getEventsListeners())); - } + rep.setEventsListeners(realm.getEventsListenersStream().collect(Collectors.toList())); - if (realm.getEnabledEventTypes() != null) { - rep.setEnabledEventTypes(new LinkedList<>(realm.getEnabledEventTypes())); - } + rep.setEnabledEventTypes(realm.getEnabledEventTypesStream().collect(Collectors.toList())); rep.setAdminEventsEnabled(realm.isAdminEventsEnabled()); @@ -763,12 +726,9 @@ public class ModelToRepresentation { rep.setProviderId(model.getProviderId()); rep.setAlias(model.getAlias()); rep.setDescription(model.getDescription()); - rep.setAuthenticationExecutions(new LinkedList<>()); - for (AuthenticationExecutionModel execution : realm.getAuthenticationExecutions(model.getId())) { - rep.getAuthenticationExecutions().add(toRepresentation(realm, execution)); - } + rep.setAuthenticationExecutions(realm.getAuthenticationExecutionsStream(model.getId()) + .map(e -> toRepresentation(realm, e)).collect(Collectors.toList())); return rep; - } public static AuthenticationExecutionExportRepresentation toRepresentation(RealmModel realm, AuthenticationExecutionModel model) { diff --git a/server-spi-private/src/main/java/org/keycloak/models/utils/RepresentationToModel.java b/server-spi-private/src/main/java/org/keycloak/models/utils/RepresentationToModel.java index d1f8bc86ce..90266529e1 100755 --- a/server-spi-private/src/main/java/org/keycloak/models/utils/RepresentationToModel.java +++ b/server-spi-private/src/main/java/org/keycloak/models/utils/RepresentationToModel.java @@ -446,7 +446,7 @@ public class RepresentationToModel { } } - if (newRealm.getComponents(newRealm.getId(), KeyProvider.class.getName()).isEmpty()) { + if (newRealm.getComponentsStream(newRealm.getId(), KeyProvider.class.getName()).count() == 0) { if (rep.getPrivateKey() != null) { DefaultKeyProviders.createProviders(newRealm, rep.getPrivateKey(), rep.getCertificate()); } else { diff --git a/server-spi-private/src/main/java/org/keycloak/protocol/AbstractLoginProtocolFactory.java b/server-spi-private/src/main/java/org/keycloak/protocol/AbstractLoginProtocolFactory.java index dd811f743c..29de53a643 100755 --- a/server-spi-private/src/main/java/org/keycloak/protocol/AbstractLoginProtocolFactory.java +++ b/server-spi-private/src/main/java/org/keycloak/protocol/AbstractLoginProtocolFactory.java @@ -25,6 +25,7 @@ import org.keycloak.models.RealmModel; import org.keycloak.provider.ProviderEvent; import org.keycloak.provider.ProviderEventListener; +import java.util.Objects; import java.util.Set; import java.util.function.Consumer; import java.util.stream.Collectors; @@ -76,12 +77,12 @@ public abstract class AbstractLoginProtocolFactory implements LoginProtocolFacto } protected void addDefaultClientScopes(RealmModel realm, Stream newClients) { - Set defaultClientScopes = realm.getDefaultClientScopes(true).stream() - .filter(clientScope -> getId().equals(clientScope.getProtocol())) + Set defaultClientScopes = realm.getDefaultClientScopesStream(true) + .filter(clientScope -> Objects.equals(getId(), clientScope.getProtocol())) .collect(Collectors.toSet()); - Set nonDefaultClientScopes = realm.getDefaultClientScopes(false).stream() - .filter(clientScope -> getId().equals(clientScope.getProtocol())) + Set nonDefaultClientScopes = realm.getDefaultClientScopesStream(false) + .filter(clientScope -> Objects.equals(getId(), clientScope.getProtocol())) .collect(Collectors.toSet()); Consumer addDefault = c -> c.addClientScopes(defaultClientScopes, true); diff --git a/server-spi-private/src/main/java/org/keycloak/utils/CredentialHelper.java b/server-spi-private/src/main/java/org/keycloak/utils/CredentialHelper.java index bc7476c11e..7537187659 100755 --- a/server-spi-private/src/main/java/org/keycloak/utils/CredentialHelper.java +++ b/server-spi-private/src/main/java/org/keycloak/utils/CredentialHelper.java @@ -17,8 +17,6 @@ package org.keycloak.utils; -import javax.ws.rs.core.Response; - import org.jboss.logging.Logger; import org.keycloak.authentication.Authenticator; import org.keycloak.authentication.AuthenticatorFactory; @@ -29,17 +27,16 @@ import org.keycloak.authentication.FormAction; import org.keycloak.authentication.FormActionFactory; import org.keycloak.credential.CredentialModel; import org.keycloak.credential.CredentialProvider; -import org.keycloak.forms.account.AccountPages; import org.keycloak.models.AuthenticationExecutionModel; -import org.keycloak.models.AuthenticationFlowModel; import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; import org.keycloak.models.UserCredentialModel; import org.keycloak.models.UserModel; import org.keycloak.models.credential.OTPCredentialModel; -import org.keycloak.models.utils.CredentialValidation; import org.keycloak.representations.idm.CredentialRepresentation; +import java.util.Objects; + /** * used to set an execution a state based on type. * @@ -61,22 +58,25 @@ public class CredentialHelper { } public static void setOrReplaceAuthenticationRequirement(KeycloakSession session, RealmModel realm, String type, AuthenticationExecutionModel.Requirement requirement, AuthenticationExecutionModel.Requirement currentRequirement) { - for (AuthenticationFlowModel flow : realm.getAuthenticationFlows()) { - for (AuthenticationExecutionModel execution : realm.getAuthenticationExecutions(flow.getId())) { - String providerId = execution.getAuthenticator(); - ConfigurableAuthenticatorFactory factory = getConfigurableAuthenticatorFactory(session, providerId); - if (factory == null) continue; - if (type.equals(factory.getReferenceCategory())) { - if (currentRequirement == null || currentRequirement.equals(execution.getRequirement())) { - execution.setRequirement(requirement); - realm.updateAuthenticatorExecution(execution); - logger.debugf("Authenticator execution '%s' switched to '%s'", execution.getAuthenticator(), requirement.toString()); - } else { - logger.debugf("Skip switch authenticator execution '%s' to '%s' as it's in state %s", execution.getAuthenticator(), requirement.toString(), execution.getRequirement()); + realm.getAuthenticationFlowsStream().forEach(flow -> realm.getAuthenticationExecutionsStream(flow.getId()) + .filter(exe -> { + ConfigurableAuthenticatorFactory factory = getConfigurableAuthenticatorFactory(session, exe.getAuthenticator()); + return Objects.nonNull(factory) && Objects.equals(type, factory.getReferenceCategory()); + }) + .filter(exe -> { + if (Objects.isNull(currentRequirement) || Objects.equals(exe.getRequirement(), currentRequirement)) + return true; + else { + logger.debugf("Skip switch authenticator execution '%s' to '%s' as it's in state %s", + exe.getAuthenticator(), requirement.toString(), exe.getRequirement()); + return false; } - } - } - } + }) + .forEachOrdered(exe -> { + exe.setRequirement(requirement); + realm.updateAuthenticatorExecution(exe); + logger.debugf("Authenticator execution '%s' switched to '%s'", exe.getAuthenticator(), requirement.toString()); + })); } public static ConfigurableAuthenticatorFactory getConfigurableAuthenticatorFactory(KeycloakSession session, String providerId) { diff --git a/server-spi-private/src/main/java/org/keycloak/utils/StreamsUtil.java b/server-spi-private/src/main/java/org/keycloak/utils/StreamsUtil.java index 3499412786..61ec1b6687 100644 --- a/server-spi-private/src/main/java/org/keycloak/utils/StreamsUtil.java +++ b/server-spi-private/src/main/java/org/keycloak/utils/StreamsUtil.java @@ -17,11 +17,29 @@ package org.keycloak.utils; +import java.util.Iterator; +import java.util.Spliterators; import java.util.function.Function; import java.util.stream.Stream; +import java.util.stream.StreamSupport; public class StreamsUtil { public static Stream closing(Stream stream) { return Stream.of(stream).flatMap(Function.identity()); } + + /** + * Returns the original stream if the stream is not empty. Otherwise throws the provided exception. + * @param stream Stream to be examined. + * @param ex Exception to be thrown if the stream is empty. + * @return Stream + */ + public static Stream throwIfEmpty(Stream stream, RuntimeException ex) { + Iterator iterator = stream.iterator(); + if (iterator.hasNext()) { + return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, 0), false); + } else { + throw ex; + } + } } diff --git a/server-spi/src/main/java/org/keycloak/credential/CredentialTypeMetadata.java b/server-spi/src/main/java/org/keycloak/credential/CredentialTypeMetadata.java index a65764cf6e..11d3f0a757 100644 --- a/server-spi/src/main/java/org/keycloak/credential/CredentialTypeMetadata.java +++ b/server-spi/src/main/java/org/keycloak/credential/CredentialTypeMetadata.java @@ -266,13 +266,10 @@ public class CredentialTypeMetadata implements ComparableBill Burke @@ -79,4 +80,17 @@ public class AuthenticationFlowModel implements Serializable { public void setBuiltIn(boolean builtIn) { this.builtIn = builtIn; } + + public static class AuthenticationFlowComparator implements Comparator { + public static final AuthenticationFlowModel.AuthenticationFlowComparator SINGLETON = + new AuthenticationFlowModel.AuthenticationFlowComparator(); + + @Override + public int compare(AuthenticationFlowModel left, AuthenticationFlowModel right) { + //ensure consistent ordering of authenticationFlows. + String l = left.getAlias() != null ? left.getAlias() : "\0"; + String r = right.getAlias() != null ? right.getAlias() : "\0"; + return l.compareTo(r); + } + } } diff --git a/server-spi/src/main/java/org/keycloak/models/AuthenticatorConfigModel.java b/server-spi/src/main/java/org/keycloak/models/AuthenticatorConfigModel.java index 308613d990..4d81d3c7b4 100755 --- a/server-spi/src/main/java/org/keycloak/models/AuthenticatorConfigModel.java +++ b/server-spi/src/main/java/org/keycloak/models/AuthenticatorConfigModel.java @@ -18,6 +18,7 @@ package org.keycloak.models; import java.io.Serializable; +import java.util.Comparator; import java.util.HashMap; import java.util.Map; @@ -57,4 +58,17 @@ public class AuthenticatorConfigModel implements Serializable { public void setConfig(Map config) { this.config = config; } + + public static class AuthenticationConfigComparator implements Comparator { + public static final AuthenticatorConfigModel.AuthenticationConfigComparator SINGLETON = + new AuthenticatorConfigModel.AuthenticationConfigComparator(); + + @Override + public int compare(AuthenticatorConfigModel left, AuthenticatorConfigModel right) { + //ensure consistent ordering of authenticationFlows. + String l = left.getAlias() != null ? left.getAlias() : "\0"; + String r = right.getAlias() != null ? right.getAlias() : "\0"; + return l.compareTo(r); + } + } } diff --git a/server-spi/src/main/java/org/keycloak/models/GroupProvider.java b/server-spi/src/main/java/org/keycloak/models/GroupProvider.java index 8a403ab58a..309bf69d69 100644 --- a/server-spi/src/main/java/org/keycloak/models/GroupProvider.java +++ b/server-spi/src/main/java/org/keycloak/models/GroupProvider.java @@ -49,7 +49,7 @@ public interface GroupProvider extends Provider, GroupLookupProvider { * * @param realm Realm. * @return List of groups in the Realm. - * @deprecated Use {@link #getGroupsStream(RealmModel)} getGroupsStream} instead. + * @deprecated Use {@link #getGroupsStream(RealmModel) getGroupsStream} instead. */ @Deprecated default List getGroups(RealmModel realm) { @@ -140,7 +140,7 @@ public interface GroupProvider extends Provider, GroupLookupProvider { * @param firstResult First result to return. Ignored if negative. * @param maxResults Maximum number of results to return. Ignored if negative. * @return List of groups with the given role. - * @deprecated Use {@link #getGroupsByRoleStream(RealmModel, RoleModel, Integer, Integer)} getGroupsByRoleStream} instead. + * @deprecated Use {@link #getGroupsByRoleStream(RealmModel, RoleModel, int, int) getGroupsByRoleStream} instead. */ @Deprecated default List getGroupsByRole(RealmModel realm, RoleModel role, int firstResult, int maxResults) { @@ -163,7 +163,7 @@ public interface GroupProvider extends Provider, GroupLookupProvider { * * @param realm Realm. * @return List of all top level groups in the realm. - * @deprecated Use {@link #getTopLevelGroupsStream(RealmModel)} getTopLevelGroupsStream} instead. + * @deprecated Use {@link #getTopLevelGroupsStream(RealmModel) getTopLevelGroupsStream} instead. */ @Deprecated default List getTopLevelGroups(RealmModel realm) { @@ -185,7 +185,7 @@ public interface GroupProvider extends Provider, GroupLookupProvider { * @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 List of top level groups in the realm. - * @deprecated Use {@link #getTopLevelGroupsStream(RealmModel, Integer, Integer)} getTopLevelGroupsStream} instead. + * @deprecated Use {@link #getTopLevelGroupsStream(RealmModel, Integer, Integer) getTopLevelGroupsStream} instead. */ @Deprecated default List getTopLevelGroups(RealmModel realm, Integer firstResult, Integer maxResults) { diff --git a/server-spi/src/main/java/org/keycloak/models/RealmModel.java b/server-spi/src/main/java/org/keycloak/models/RealmModel.java index 0765714bf1..649d9b7104 100755 --- a/server-spi/src/main/java/org/keycloak/models/RealmModel.java +++ b/server-spi/src/main/java/org/keycloak/models/RealmModel.java @@ -246,7 +246,15 @@ public interface RealmModel extends RoleContainerModel { int getActionTokenGeneratedByUserLifespan(String actionTokenType); void setActionTokenGeneratedByUserLifespan(String actionTokenType, Integer seconds); - List getRequiredCredentials(); + /** + * @deprecated Use {@link #getRequiredCredentialsStream() getRequiredCredentialsStream} instead. + */ + @Deprecated + default List getRequiredCredentials() { + return getRequiredCredentialsStream().collect(Collectors.toList()); + } + + Stream getRequiredCredentialsStream(); void addRequiredCredential(String cred); @@ -360,42 +368,115 @@ public interface RealmModel extends RoleContainerModel { AuthenticationFlowModel getDockerAuthenticationFlow(); void setDockerAuthenticationFlow(AuthenticationFlowModel flow); - List getAuthenticationFlows(); + /** + * @deprecated Use {@link #getAuthenticationFlowsStream() getAuthenticationFlowsStream} instead. + */ + @Deprecated + default List getAuthenticationFlows() { + return getAuthenticationFlowsStream().collect(Collectors.toList()); + } + + Stream getAuthenticationFlowsStream(); + AuthenticationFlowModel getFlowByAlias(String alias); AuthenticationFlowModel addAuthenticationFlow(AuthenticationFlowModel model); AuthenticationFlowModel getAuthenticationFlowById(String id); void removeAuthenticationFlow(AuthenticationFlowModel model); void updateAuthenticationFlow(AuthenticationFlowModel model); - List getAuthenticationExecutions(String flowId); + /** + * @deprecated Use {@link #getAuthenticationExecutionsStream(String) getAuthenticationExecutionsStream} instead. + */ + @Deprecated + default List getAuthenticationExecutions(String flowId) { + return getAuthenticationExecutionsStream(flowId).collect(Collectors.toList()); + } + + /** + * Returns sorted {@link AuthenticationExecutionModel AuthenticationExecutionModel} as a stream. + * It should be used with forEachOrdered if the ordering is required. + * @return Sorted stream + */ + Stream getAuthenticationExecutionsStream(String flowId); + AuthenticationExecutionModel getAuthenticationExecutionById(String id); AuthenticationExecutionModel getAuthenticationExecutionByFlowId(String flowId); AuthenticationExecutionModel addAuthenticatorExecution(AuthenticationExecutionModel model); void updateAuthenticatorExecution(AuthenticationExecutionModel model); void removeAuthenticatorExecution(AuthenticationExecutionModel model); + /** + * @deprecated Use {@link #getAuthenticatorConfigsStream() getAuthenticatorConfigsStream} instead. + */ + @Deprecated + default List getAuthenticatorConfigs() { + return getAuthenticatorConfigsStream().collect(Collectors.toList()); + } + + Stream getAuthenticatorConfigsStream(); - List getAuthenticatorConfigs(); AuthenticatorConfigModel addAuthenticatorConfig(AuthenticatorConfigModel model); void updateAuthenticatorConfig(AuthenticatorConfigModel model); void removeAuthenticatorConfig(AuthenticatorConfigModel model); AuthenticatorConfigModel getAuthenticatorConfigById(String id); AuthenticatorConfigModel getAuthenticatorConfigByAlias(String alias); - List getRequiredActionProviders(); + /** + * @deprecated Use {@link #getRequiredActionProvidersStream() getRequiredActionProvidersStream} instead. + */ + @Deprecated + default List getRequiredActionProviders() { + return getRequiredActionProvidersStream().collect(Collectors.toList()); + } + + /** + * Returns sorted {@link RequiredActionProviderModel RequiredActionProviderModel} as a stream. + * It should be used with forEachOrdered if the ordering is required. + * @return Sorted stream + */ + Stream getRequiredActionProvidersStream(); + RequiredActionProviderModel addRequiredActionProvider(RequiredActionProviderModel model); void updateRequiredActionProvider(RequiredActionProviderModel model); void removeRequiredActionProvider(RequiredActionProviderModel model); RequiredActionProviderModel getRequiredActionProviderById(String id); RequiredActionProviderModel getRequiredActionProviderByAlias(String alias); - List getIdentityProviders(); + /** + * @deprecated Use {@link #getIdentityProvidersStream() getIdentityProvidersStream} instead. + */ + @Deprecated + default List getIdentityProviders() { + return getIdentityProvidersStream().collect(Collectors.toList()); + } + + Stream getIdentityProvidersStream(); + IdentityProviderModel getIdentityProviderByAlias(String alias); void addIdentityProvider(IdentityProviderModel identityProvider); void removeIdentityProviderByAlias(String alias); void updateIdentityProvider(IdentityProviderModel identityProvider); - Set getIdentityProviderMappers(); - Set getIdentityProviderMappersByAlias(String brokerAlias); + + /** + * @deprecated Use {@link #getIdentityProviderMappersStream() getIdentityProviderMappersStream} instead. + */ + @Deprecated + default Set getIdentityProviderMappers() { + return getIdentityProviderMappersStream().collect(Collectors.toSet()); + } + + Stream getIdentityProviderMappersStream(); + + /** + * @deprecated Use {@link #getIdentityProviderMappersByAliasStream(String) getIdentityProviderMappersByAliasStream} instead. + */ + @Deprecated + default Set getIdentityProviderMappersByAlias(String brokerAlias) { + return getIdentityProviderMappersByAliasStream(brokerAlias).collect(Collectors.toSet()); + } + + Stream getIdentityProviderMappersByAliasStream(String brokerAlias); + IdentityProviderMapperModel addIdentityProviderMapper(IdentityProviderMapperModel model); void removeIdentityProviderMapper(IdentityProviderMapperModel mapping); void updateIdentityProviderMapper(IdentityProviderMapperModel mapping); @@ -422,7 +503,15 @@ public interface RealmModel extends RoleContainerModel { void updateComponent(ComponentModel component); void removeComponent(ComponentModel component); void removeComponents(String parentId); - List getComponents(String parentId, String providerType); + + /** + * @deprecated Use {@link #getComponentsStream(String, String) getComponentsStream} instead. + */ + @Deprecated + default List getComponents(String parentId, String providerType) { + return getComponentsStream(parentId, providerType).collect(Collectors.toList()); + } + /** * Returns stream of ComponentModels for specific parentId and providerType. @@ -430,43 +519,85 @@ public interface RealmModel extends RoleContainerModel { * @param providerType type of provider * @return stream of ComponentModels */ - default Stream getComponentsStream(String parentId, String providerType) { - return getComponents(parentId, providerType).stream(); + Stream getComponentsStream(String parentId, String providerType); + + Stream getComponentsStream(String parentId); + + /** + * @deprecated Use {@link #getComponentsStream(String) getComponentsStream} instead. + */ + @Deprecated + default List getComponents(String parentId) { + return getComponentsStream(parentId).collect(Collectors.toList()); } - List getComponents(String parentId); + /** + * @deprecated Use {@link #getComponentsStream() getComponentsStream} instead. + */ + @Deprecated + default List getComponents() { + return getComponentsStream().collect(Collectors.toList()); + } + + Stream getComponentsStream(); - List getComponents(); ComponentModel getComponent(String id); - default - List getUserStorageProviders() { - List list = new LinkedList<>(); - for (ComponentModel component : getComponents(getId(), UserStorageProvider.class.getName())) { - list.add(new UserStorageProviderModel(component)); - } - Collections.sort(list, UserStorageProviderModel.comparator); - return list; + /** + * @deprecated Use {@link #getUserStorageProvidersStream() getUserStorageProvidersStream} instead. + */ + @Deprecated + default List getUserStorageProviders() { + return getUserStorageProvidersStream().collect(Collectors.toList()); } - default - List getClientStorageProviders() { - List list = new LinkedList<>(); - for (ComponentModel component : getComponents(getId(), ClientStorageProvider.class.getName())) { - list.add(new ClientStorageProviderModel(component)); - } - Collections.sort(list, ClientStorageProviderModel.comparator); - return list; + /** + * Returns sorted {@link UserStorageProviderModel UserStorageProviderModel} as a stream. + * It should be used with forEachOrdered if the ordering is required. + * @return Sorted stream + */ + default Stream getUserStorageProvidersStream() { + return getComponentsStream(getId(), UserStorageProvider.class.getName()) + .map(UserStorageProviderModel::new) + .sorted(UserStorageProviderModel.comparator); } - default - List getRoleStorageProviders() { - List list = new LinkedList<>(); - for (ComponentModel component : getComponents(getId(), RoleStorageProvider.class.getName())) { - list.add(new RoleStorageProviderModel(component)); - } - Collections.sort(list, RoleStorageProviderModel.comparator); - return list; + /** + * @deprecated Use {@link #getClientStorageProvidersStream() getClientStorageProvidersStream} instead. + */ + @Deprecated + default List getClientStorageProviders() { + return getClientStorageProvidersStream().collect(Collectors.toList()); + } + + /** + * Returns sorted {@link ClientStorageProviderModel ClientStorageProviderModel} as a stream. + * It should be used with forEachOrdered if the ordering is required. + * @return Sorted stream + */ + default Stream getClientStorageProvidersStream() { + return getComponentsStream(getId(), ClientStorageProvider.class.getName()) + .map(ClientStorageProviderModel::new) + .sorted(ClientStorageProviderModel.comparator); + } + + /** + * @deprecated Use {@link #getRoleStorageProvidersStream() getRoleStorageProvidersStream} instead. + */ + @Deprecated + default List getRoleStorageProviders() { + return getRoleStorageProvidersStream().collect(Collectors.toList()); + } + + /** + * Returns sorted {@link RoleStorageProviderModel RoleStorageProviderModel} as a stream. + * It should be used with forEachOrdered if the ordering is required. + * @return Sorted stream + */ + default Stream getRoleStorageProvidersStream() { + return getComponentsStream(getId(), RoleStorageProvider.class.getName()) + .map(RoleStorageProviderModel::new) + .sorted(RoleStorageProviderModel.comparator); } /** @@ -516,11 +647,27 @@ public interface RealmModel extends RoleContainerModel { void setEventsExpiration(long expiration); - Set getEventsListeners(); + /** + * @deprecated Use {@link #getEventsListenersStream() getEventsListenersStream} instead. + */ + @Deprecated + default Set getEventsListeners() { + return getEventsListenersStream().collect(Collectors.toSet()); + } + + Stream getEventsListenersStream(); void setEventsListeners(Set listeners); - Set getEnabledEventTypes(); + /** + * @deprecated Use {@link #getEnabledEventTypesStream() getEnabledEventTypesStream} instead. + */ + @Deprecated + default Set getEnabledEventTypes() { + return getEnabledEventTypesStream().collect(Collectors.toSet()); + } + + Stream getEnabledEventTypesStream(); void setEnabledEventTypes(Set enabledEventTypes); @@ -540,7 +687,17 @@ public interface RealmModel extends RoleContainerModel { boolean isInternationalizationEnabled(); void setInternationalizationEnabled(boolean enabled); - Set getSupportedLocales(); + + /** + * @deprecated Use {@link #getSupportedLocalesStream() getSupportedLocalesStream} instead. + */ + @Deprecated + default Set getSupportedLocales() { + return getSupportedLocalesStream().collect(Collectors.toSet()); + } + + Stream getSupportedLocalesStream(); + void setSupportedLocales(Set locales); String getDefaultLocale(); void setDefaultLocale(String locale); @@ -561,6 +718,9 @@ public interface RealmModel extends RoleContainerModel { GroupModel getGroupById(String id); + /** + * @deprecated Use {@link #getGroupsStream() getGroupsStream} instead. + */ @Deprecated default List getGroups() { return getGroupsStream().collect(Collectors.toList()); @@ -571,6 +731,9 @@ public interface RealmModel extends RoleContainerModel { Long getGroupsCount(Boolean onlyTopGroups); Long getGroupsCountByNameContaining(String search); + /** + * @deprecated Use {@link #getTopLevelGroups() getTopLevelGroups} instead. + */ @Deprecated default List getTopLevelGroups() { return getTopLevelGroupsStream().collect(Collectors.toList()); @@ -578,6 +741,9 @@ public interface RealmModel extends RoleContainerModel { Stream getTopLevelGroupsStream(); + /** + * @deprecated Use {@link #getTopLevelGroupsStream(Integer, Integer) getTopLevelGroupsStream} instead. + */ @Deprecated default List getTopLevelGroups(Integer first, Integer max) { return getTopLevelGroupsStream(first, max).collect(Collectors.toList()); @@ -585,6 +751,9 @@ public interface RealmModel extends RoleContainerModel { Stream getTopLevelGroupsStream(Integer first, Integer max); + /** + * @deprecated Use {@link #searchForGroupByNameStream(String, Integer, Integer) searchForGroupByName} instead. + */ @Deprecated default List searchForGroupByName(String search, Integer first, Integer max) { return searchForGroupByNameStream(search, first, max).collect(Collectors.toList()); @@ -595,7 +764,15 @@ public interface RealmModel extends RoleContainerModel { boolean removeGroup(GroupModel group); void moveGroup(GroupModel group, GroupModel toParent); - List getClientScopes(); + /** + * @deprecated Use {@link #getClientScopesStream() getClientScopesStream} instead. + */ + @Deprecated + default List getClientScopes() { + return getClientScopesStream().collect(Collectors.toList()); + } + + Stream getClientScopesStream(); ClientScopeModel addClientScope(String name); @@ -607,6 +784,14 @@ public interface RealmModel extends RoleContainerModel { void addDefaultClientScope(ClientScopeModel clientScope, boolean defaultScope); void removeDefaultClientScope(ClientScopeModel clientScope); - List getDefaultClientScopes(boolean defaultScope); + /** + * @deprecated Use {@link #getDefaultClientScopesStream(boolean) getDefaultClientScopesStream} instead. + */ + @Deprecated + default List getDefaultClientScopes(boolean defaultScope) { + return getDefaultClientScopesStream(defaultScope).collect(Collectors.toList()); + } + + Stream getDefaultClientScopesStream(boolean defaultScope); } diff --git a/server-spi/src/main/java/org/keycloak/models/RealmProvider.java b/server-spi/src/main/java/org/keycloak/models/RealmProvider.java index c6034f2b6f..e2668be3db 100755 --- a/server-spi/src/main/java/org/keycloak/models/RealmProvider.java +++ b/server-spi/src/main/java/org/keycloak/models/RealmProvider.java @@ -23,6 +23,7 @@ import org.keycloak.provider.Provider; import java.util.List; import java.util.Set; import java.util.stream.Collectors; +import java.util.stream.Stream; /** * @author Bill Burke @@ -39,14 +40,43 @@ public interface RealmProvider extends Provider /* TODO: Remove in future versio ClientScopeModel getClientScopeById(String id, RealmModel realm); - List getRealms(); - List getRealmsWithProviderType(Class type); + /** + * @deprecated Use {@link #getRealmsStream() getRealmsStream} instead. + */ + @Deprecated + default List getRealms() { + return getRealmsStream().collect(Collectors.toList()); + } + + Stream getRealmsStream(); + + /** + * @deprecated Use {@link #getRealmsWithProviderTypeStream(Class)} getRealmsWithProviderTypeStream} instead. + */ + @Deprecated + default List getRealmsWithProviderType(Class type) { + return getRealmsWithProviderTypeStream(type).collect(Collectors.toList()); + } + + Stream getRealmsWithProviderTypeStream(Class type); + + boolean removeRealm(String id); ClientInitialAccessModel createClientInitialAccessModel(RealmModel realm, int expiration, int count); ClientInitialAccessModel getClientInitialAccessModel(RealmModel realm, String id); void removeClientInitialAccessModel(RealmModel realm, String id); - List listClientInitialAccess(RealmModel realm); + + /** + * @deprecated Use {@link #listClientInitialAccessStream(RealmModel)} listClientInitialAccessStream} instead. + */ + @Deprecated + default List listClientInitialAccess(RealmModel realm) { + return listClientInitialAccessStream(realm).collect(Collectors.toList()); + } + + Stream listClientInitialAccessStream(RealmModel realm); + void removeExpiredClientInitialAccess(); void decreaseRemainingCount(RealmModel realm, ClientInitialAccessModel clientInitialAccess); // Separate provider method to ensure we decrease remainingCount atomically instead of doing classic update diff --git a/server-spi/src/main/java/org/keycloak/storage/group/GroupLookupProvider.java b/server-spi/src/main/java/org/keycloak/storage/group/GroupLookupProvider.java index 150620c7e6..100ab01af5 100644 --- a/server-spi/src/main/java/org/keycloak/storage/group/GroupLookupProvider.java +++ b/server-spi/src/main/java/org/keycloak/storage/group/GroupLookupProvider.java @@ -42,7 +42,7 @@ public interface GroupLookupProvider { * @param firstResult First result to return. Ignored if {@code null}. * @param maxResults Maximum number of results to return. Ignored if {@code null}. * @return List of groups with the given string in name. - * @deprecated Use {@link #searchForGroupByNameStream(RealmModel, String, Integer, Integer)} searchForGroupByNameStream} instead. + * @deprecated Use {@link #searchForGroupByNameStream(RealmModel, String, Integer, Integer) searchForGroupByNameStream} instead. */ @Deprecated default List searchForGroupByName(RealmModel realm, String search, Integer firstResult, Integer maxResults) { diff --git a/services/src/main/java/org/keycloak/authentication/AuthenticationProcessor.java b/services/src/main/java/org/keycloak/authentication/AuthenticationProcessor.java index 3ec650cf6d..6ff8b0fb2d 100755 --- a/services/src/main/java/org/keycloak/authentication/AuthenticationProcessor.java +++ b/services/src/main/java/org/keycloak/authentication/AuthenticationProcessor.java @@ -39,7 +39,6 @@ import org.keycloak.models.UserModel; import org.keycloak.models.UserSessionModel; import org.keycloak.models.utils.AuthenticationFlowResolver; import org.keycloak.models.utils.FormMessage; -import org.keycloak.models.utils.KeycloakModelUtils; import org.keycloak.protocol.LoginProtocol; import org.keycloak.protocol.LoginProtocol.Error; import org.keycloak.protocol.oidc.TokenManager; @@ -302,15 +301,15 @@ public class AuthenticationProcessor { @Override public AuthenticationExecutionModel.Requirement getCategoryRequirementFromCurrentFlow(String authenticatorCategory) { - List executions = realm.getAuthenticationExecutions(execution.getParentFlow()); - for (AuthenticationExecutionModel exe : executions) { - AuthenticatorFactory factory = (AuthenticatorFactory) getSession().getKeycloakSessionFactory().getProviderFactory(Authenticator.class, exe.getAuthenticator()); - if (factory != null && factory.getReferenceCategory().equals(authenticatorCategory)) { - return exe.getRequirement(); - } - - } - return null; + return realm.getAuthenticationExecutionsStream(execution.getParentFlow()) + .filter(e -> { + AuthenticatorFactory factory = (AuthenticatorFactory) getSession().getKeycloakSessionFactory() + .getProviderFactory(Authenticator.class, e.getAuthenticator()); + return factory != null && factory.getReferenceCategory().equals(authenticatorCategory); + }) + .map(AuthenticationExecutionModel::getRequirement) + .findFirst() + .orElse(null); } @Override @@ -1045,7 +1044,7 @@ public class AuthenticationProcessor { } public void evaluateRequiredActionTriggers() { - AuthenticationManager.evaluateRequiredActionTriggers(session, authenticationSession, connection, request, uriInfo, event, realm, authenticationSession.getAuthenticatedUser()); + AuthenticationManager.evaluateRequiredActionTriggers(session, authenticationSession, request, event, realm, authenticationSession.getAuthenticatedUser()); } public Response finishAuthentication(LoginProtocol protocol) { @@ -1076,7 +1075,7 @@ public class AuthenticationProcessor { } public String nextRequiredAction() { - return AuthenticationManager.nextRequiredAction(session, authenticationSession, connection, request, uriInfo, event); + return AuthenticationManager.nextRequiredAction(session, authenticationSession, request, event); } public AuthenticationProcessor.Result createAuthenticatorContext(AuthenticationExecutionModel model, Authenticator authenticator, List executions) { diff --git a/services/src/main/java/org/keycloak/authentication/AuthenticationSelectionResolver.java b/services/src/main/java/org/keycloak/authentication/AuthenticationSelectionResolver.java index 79d597d707..7996b8dece 100644 --- a/services/src/main/java/org/keycloak/authentication/AuthenticationSelectionResolver.java +++ b/services/src/main/java/org/keycloak/authentication/AuthenticationSelectionResolver.java @@ -24,10 +24,6 @@ import java.util.List; import java.util.Map; import java.util.stream.Collectors; -import javax.ws.rs.core.Form; -import javax.ws.rs.core.MultivaluedHashMap; -import javax.ws.rs.core.MultivaluedMap; - import org.jboss.logging.Logger; import org.keycloak.credential.CredentialModel; import org.keycloak.models.AuthenticationExecutionModel; @@ -136,7 +132,8 @@ class AuthenticationSelectionResolver { } // Find the corresponding execution. If it is 1st REQUIRED execution in the particular subflow, we need to consider parent flow as well - List executions = realm.getAuthenticationExecutions(execution.getParentFlow()); + List executions = realm.getAuthenticationExecutionsStream(execution.getParentFlow()) + .collect(Collectors.toList()); int executionIndex = executions.indexOf(execution); if (executionIndex != 0) { return flowId; @@ -188,11 +185,9 @@ class AuthenticationSelectionResolver { logger.debugf("Going through the flow '%s' for adding executions", flowModel.getAlias()); - List executions = processor.getRealm().getAuthenticationExecutions(flowId); - List requiredList = new ArrayList<>(); List alternativeList = new ArrayList<>(); - flow.fillListsOfExecutions(executions, requiredList, alternativeList); + flow.fillListsOfExecutions(processor.getRealm().getAuthenticationExecutionsStream(flowId), requiredList, alternativeList); // If requiredList is not empty, we're going to collect just very first execution from the flow if (!requiredList.isEmpty()) { diff --git a/services/src/main/java/org/keycloak/authentication/AuthenticatorUtil.java b/services/src/main/java/org/keycloak/authentication/AuthenticatorUtil.java deleted file mode 100755 index 1c18b66d57..0000000000 --- a/services/src/main/java/org/keycloak/authentication/AuthenticatorUtil.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2016 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.keycloak.authentication; - -import org.keycloak.models.AuthenticationExecutionModel; -import org.keycloak.models.RealmModel; - -import java.util.LinkedList; -import java.util.List; - -/** - * @author Bill Burke - * @version $Revision: 1 $ - */ -public class AuthenticatorUtil { - - public static List getEnabledExecutionsRecursively(RealmModel realm, String flowId) { - List executions = new LinkedList<>(); - recurseExecutions(realm, flowId, executions); - return executions; - - } - - public static void recurseExecutions(RealmModel realm, String flowId, List executions) { - List authenticationExecutions = realm.getAuthenticationExecutions(flowId); - if (authenticationExecutions == null) return; - for (AuthenticationExecutionModel model : authenticationExecutions) { - executions.add(model); - if (model.isAuthenticatorFlow() && model.isEnabled()) { - recurseExecutions(realm, model.getFlowId(), executions); - } - } - } - - public static AuthenticationExecutionModel findExecutionByAuthenticator(RealmModel realm, String flowId, String authProviderId) { - for (AuthenticationExecutionModel model : realm.getAuthenticationExecutions(flowId)) { - if (model.isAuthenticatorFlow()) { - AuthenticationExecutionModel recurse = findExecutionByAuthenticator(realm, model.getFlowId(), authProviderId); - if (recurse != null) return recurse; - - } - if (model.getAuthenticator().equals(authProviderId)) { - return model; - } - } - return null; - } - - public static boolean isEnabled(RealmModel realm, String flowId, String authProviderId) { - AuthenticationExecutionModel execution = findExecutionByAuthenticator(realm, flowId, authProviderId); - if (execution == null) { - return false; - } - return execution.isEnabled(); - } - public static boolean isRequired(RealmModel realm, String flowId, String authProviderId) { - AuthenticationExecutionModel execution = findExecutionByAuthenticator(realm, flowId, authProviderId); - if (execution == null) { - return false; - } - return execution.isRequired(); - } -} diff --git a/services/src/main/java/org/keycloak/authentication/ClientAuthenticationFlow.java b/services/src/main/java/org/keycloak/authentication/ClientAuthenticationFlow.java index bddb415b0f..8e6eda6789 100755 --- a/services/src/main/java/org/keycloak/authentication/ClientAuthenticationFlow.java +++ b/services/src/main/java/org/keycloak/authentication/ClientAuthenticationFlow.java @@ -29,7 +29,9 @@ import org.keycloak.services.ServicesLogger; import javax.ws.rs.core.Response; import java.util.ArrayList; import java.util.Arrays; +import java.util.LinkedList; import java.util.List; +import java.util.Optional; /** * @author Marek Posolda @@ -106,19 +108,23 @@ public class ClientAuthenticationFlow implements AuthenticationFlow { } protected List findExecutionsToRun() { - List executions = processor.getRealm().getAuthenticationExecutions(flow.getId()); - List executionsToRun = new ArrayList<>(); + List executionsToRun = new LinkedList<>(); + List finalExecutionsToRun = executionsToRun; + Optional first = processor.getRealm().getAuthenticationExecutionsStream(flow.getId()) + .filter(e -> { + if (e.isRequired()) { + return true; + } else if (e.isAlternative()){ + finalExecutionsToRun.add(e); + return false; + } + return false; + }).findFirst(); - for (AuthenticationExecutionModel execution : executions) { - if (execution.isRequired()) { - executionsToRun = Arrays.asList(execution); - break; - } - - if (execution.isAlternative()) { - executionsToRun.add(execution); - } - } + if (first.isPresent()) + executionsToRun = Arrays.asList(first.get()); + else + executionsToRun.addAll(finalExecutionsToRun); if (logger.isTraceEnabled()) { List exIds = new ArrayList<>(); diff --git a/services/src/main/java/org/keycloak/authentication/DefaultAuthenticationFlow.java b/services/src/main/java/org/keycloak/authentication/DefaultAuthenticationFlow.java index 4e512a15f7..d8dbd81b1d 100755 --- a/services/src/main/java/org/keycloak/authentication/DefaultAuthenticationFlow.java +++ b/services/src/main/java/org/keycloak/authentication/DefaultAuthenticationFlow.java @@ -23,7 +23,6 @@ import org.keycloak.authentication.authenticators.conditional.ConditionalAuthent import org.keycloak.models.AuthenticationExecutionModel; import org.keycloak.models.AuthenticationFlowModel; import org.keycloak.models.Constants; -import org.keycloak.models.RealmModel; import org.keycloak.models.UserModel; import org.keycloak.services.ServicesLogger; import org.keycloak.sessions.AuthenticationSessionModel; @@ -35,7 +34,9 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedList; import java.util.List; +import java.util.function.Predicate; import java.util.stream.Collectors; +import java.util.stream.Stream; /** * @author Bill Burke @@ -52,7 +53,7 @@ public class DefaultAuthenticationFlow implements AuthenticationFlow { public DefaultAuthenticationFlow(AuthenticationProcessor processor, AuthenticationFlowModel flow) { this.processor = processor; this.flow = flow; - this.executions = processor.getRealm().getAuthenticationExecutions(flow.getId()); + this.executions = processor.getRealm().getAuthenticationExecutionsStream(flow.getId()).collect(Collectors.toList()); } protected boolean isProcessed(AuthenticationExecutionModel model) { @@ -204,13 +205,13 @@ public class DefaultAuthenticationFlow implements AuthenticationFlow { */ private String checkAndValidateParentFlow(AuthenticationExecutionModel model) { while (true) { - List localExecutions = processor.getRealm().getAuthenticationExecutions(model.getParentFlow()); AuthenticationExecutionModel parentFlowExecutionModel = processor.getRealm().getAuthenticationExecutionByFlowId(model.getParentFlow()); if (parentFlowExecutionModel != null) { List requiredExecutions = new LinkedList<>(); List alternativeExecutions = new LinkedList<>(); - fillListsOfExecutions(localExecutions, requiredExecutions, alternativeExecutions); + fillListsOfExecutions(processor.getRealm().getAuthenticationExecutionsStream(model.getParentFlow()), + requiredExecutions, alternativeExecutions); // Note: If we evaluate alternative execution, we will also doublecheck that there are not required elements in same subflow if ((model.isRequired() && requiredExecutions.stream().allMatch(processor::isSuccessful)) || @@ -237,7 +238,7 @@ public class DefaultAuthenticationFlow implements AuthenticationFlow { List requiredList = new ArrayList<>(); List alternativeList = new ArrayList<>(); - fillListsOfExecutions(executions, requiredList, alternativeList); + fillListsOfExecutions(executions.stream(), requiredList, alternativeList); //handle required elements : all required elements need to be executed boolean requiredElementsSuccessful = true; @@ -296,16 +297,16 @@ public class DefaultAuthenticationFlow implements AuthenticationFlow { /** * Just iterates over executionsToProcess and fill "requiredList" and "alternativeList" according to it */ - void fillListsOfExecutions(List executionsToProcess, List requiredList, List alternativeList) { - for (AuthenticationExecutionModel execution : executionsToProcess) { - if (isConditionalAuthenticator(execution)) { - continue; - } else if (execution.isRequired() || execution.isConditional()) { - requiredList.add(execution); - } else if (execution.isAlternative()) { - alternativeList.add(execution); - } - } + void fillListsOfExecutions(Stream executionsToProcess, List requiredList, List alternativeList) { + executionsToProcess + .filter(((Predicate) this::isConditionalAuthenticator).negate()) + .forEachOrdered(execution -> { + if (execution.isRequired() || execution.isConditional()) { + requiredList.add(execution); + } else if (execution.isAlternative()) { + alternativeList.add(execution); + } + }); if (!requiredList.isEmpty() && !alternativeList.isEmpty()) { List alternativeIds = alternativeList.stream() @@ -327,12 +328,14 @@ public class DefaultAuthenticationFlow implements AuthenticationFlow { if (model == null || !model.isAuthenticatorFlow() || !model.isConditional()) { return false; }; - List modelList = processor.getRealm().getAuthenticationExecutions(model.getFlowId()); + List modelList = processor.getRealm() + .getAuthenticationExecutionsStream(model.getFlowId()).collect(Collectors.toList()); List conditionalAuthenticatorList = modelList.stream() .filter(this::isConditionalAuthenticator) .filter(s -> s.isEnabled()) .collect(Collectors.toList()); - return conditionalAuthenticatorList.isEmpty() || conditionalAuthenticatorList.stream().anyMatch(m-> conditionalNotMatched(m, modelList)); + return conditionalAuthenticatorList.isEmpty() || conditionalAuthenticatorList.stream() + .anyMatch(m -> conditionalNotMatched(m, modelList)); } private boolean isConditionalAuthenticator(AuthenticationExecutionModel model) { diff --git a/services/src/main/java/org/keycloak/authentication/FormAuthenticationFlow.java b/services/src/main/java/org/keycloak/authentication/FormAuthenticationFlow.java index 240fa8098c..b54d481fcd 100755 --- a/services/src/main/java/org/keycloak/authentication/FormAuthenticationFlow.java +++ b/services/src/main/java/org/keycloak/authentication/FormAuthenticationFlow.java @@ -42,6 +42,7 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.stream.Collectors; /** * @author Bill Burke @@ -57,7 +58,7 @@ public class FormAuthenticationFlow implements AuthenticationFlow { public FormAuthenticationFlow(AuthenticationProcessor processor, AuthenticationExecutionModel execution) { this.processor = processor; this.formExecution = execution; - formActionExecutions = processor.getRealm().getAuthenticationExecutions(execution.getFlowId()); + formActionExecutions = processor.getRealm().getAuthenticationExecutionsStream(execution.getFlowId()).collect(Collectors.toList()); formAuthenticator = processor.getSession().getProvider(FormAuthenticator.class, execution.getAuthenticator()); } diff --git a/services/src/main/java/org/keycloak/authentication/actiontoken/execactions/ExecuteActionsActionTokenHandler.java b/services/src/main/java/org/keycloak/authentication/actiontoken/execactions/ExecuteActionsActionTokenHandler.java index b5c9164e07..8d4738cea6 100644 --- a/services/src/main/java/org/keycloak/authentication/actiontoken/execactions/ExecuteActionsActionTokenHandler.java +++ b/services/src/main/java/org/keycloak/authentication/actiontoken/execactions/ExecuteActionsActionTokenHandler.java @@ -103,7 +103,7 @@ public class ExecuteActionsActionTokenHandler extends AbstractActionTokenHander< // verify user email as we know it is valid as this entry point would never have gotten here. user.setEmailVerified(true); - String nextAction = AuthenticationManager.nextRequiredAction(tokenContext.getSession(), authSession, tokenContext.getClientConnection(), tokenContext.getRequest(), tokenContext.getUriInfo(), tokenContext.getEvent()); + String nextAction = AuthenticationManager.nextRequiredAction(tokenContext.getSession(), authSession, tokenContext.getRequest(), tokenContext.getEvent()); return AuthenticationManager.redirectToRequiredActions(tokenContext.getSession(), tokenContext.getRealm(), authSession, tokenContext.getUriInfo(), nextAction); } diff --git a/services/src/main/java/org/keycloak/authentication/actiontoken/verifyemail/VerifyEmailActionTokenHandler.java b/services/src/main/java/org/keycloak/authentication/actiontoken/verifyemail/VerifyEmailActionTokenHandler.java index ff497c829d..ad27e95fca 100644 --- a/services/src/main/java/org/keycloak/authentication/actiontoken/verifyemail/VerifyEmailActionTokenHandler.java +++ b/services/src/main/java/org/keycloak/authentication/actiontoken/verifyemail/VerifyEmailActionTokenHandler.java @@ -111,7 +111,7 @@ public class VerifyEmailActionTokenHandler extends AbstractActionTokenHander requestHeaders = session.getContext().getRequestHeaders().getRequestHeaders(); - for (AuthenticatorConfigModel configModel : realm.getAuthenticatorConfigs()) { - + return realm.getAuthenticatorConfigsStream().anyMatch(configModel -> { if (tryConcludeBasedOn(voteForUserOtpControlAttribute(user, configModel.getConfig()))) { return true; } @@ -311,8 +309,8 @@ public class ConditionalOtpFormAuthenticator extends OTPFormAuthenticator { || voteForDefaultFallback(configModel.getConfig()) == ABSTAIN)) { return true; } - } - return false; + return false; + }); } private boolean containsConditionalOtpConfig(Map config) { diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/browser/IdentityProviderAuthenticator.java b/services/src/main/java/org/keycloak/authentication/authenticators/browser/IdentityProviderAuthenticator.java index a70a100d61..ededd493ed 100644 --- a/services/src/main/java/org/keycloak/authentication/authenticators/browser/IdentityProviderAuthenticator.java +++ b/services/src/main/java/org/keycloak/authentication/authenticators/browser/IdentityProviderAuthenticator.java @@ -34,7 +34,8 @@ import org.keycloak.services.managers.ClientSessionCode; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriBuilder; import java.net.URI; -import java.util.List; +import java.util.Objects; +import java.util.Optional; /** * @author Stian Thorgersen @@ -67,27 +68,28 @@ public class IdentityProviderAuthenticator implements Authenticator { } private void redirect(AuthenticationFlowContext context, String providerId) { - List identityProviders = context.getRealm().getIdentityProviders(); - for (IdentityProviderModel identityProvider : identityProviders) { - if (identityProvider.isEnabled() && providerId.equals(identityProvider.getAlias())) { - String accessCode = new ClientSessionCode<>(context.getSession(), context.getRealm(), context.getAuthenticationSession()).getOrGenerateCode(); - String clientId = context.getAuthenticationSession().getClient().getClientId(); - String tabId = context.getAuthenticationSession().getTabId(); - URI location = Urls.identityProviderAuthnRequest(context.getUriInfo().getBaseUri(), providerId, context.getRealm().getName(), accessCode, clientId, tabId); - if (context.getAuthenticationSession().getClientNote(OAuth2Constants.DISPLAY) != null) { - location = UriBuilder.fromUri(location).queryParam(OAuth2Constants.DISPLAY, context.getAuthenticationSession().getClientNote(OAuth2Constants.DISPLAY)).build(); - } - Response response = Response.seeOther(location) - .build(); - // will forward the request to the IDP with prompt=none if the IDP accepts forwards with prompt=none. - if ("none".equals(context.getAuthenticationSession().getClientNote(OIDCLoginProtocol.PROMPT_PARAM)) && - Boolean.valueOf(identityProvider.getConfig().get(ACCEPTS_PROMPT_NONE))) { - context.getAuthenticationSession().setAuthNote(AuthenticationProcessor.FORWARDED_PASSIVE_LOGIN, "true"); - } - LOG.debugf("Redirecting to %s", providerId); - context.forceChallenge(response); - return; + Optional idp = context.getRealm().getIdentityProvidersStream() + .filter(IdentityProviderModel::isEnabled) + .filter(identityProvider -> Objects.equals(providerId, identityProvider.getAlias())) + .findFirst(); + if (idp.isPresent()) { + String accessCode = new ClientSessionCode<>(context.getSession(), context.getRealm(), context.getAuthenticationSession()).getOrGenerateCode(); + String clientId = context.getAuthenticationSession().getClient().getClientId(); + String tabId = context.getAuthenticationSession().getTabId(); + URI location = Urls.identityProviderAuthnRequest(context.getUriInfo().getBaseUri(), providerId, context.getRealm().getName(), accessCode, clientId, tabId); + if (context.getAuthenticationSession().getClientNote(OAuth2Constants.DISPLAY) != null) { + location = UriBuilder.fromUri(location).queryParam(OAuth2Constants.DISPLAY, context.getAuthenticationSession().getClientNote(OAuth2Constants.DISPLAY)).build(); } + Response response = Response.seeOther(location) + .build(); + // will forward the request to the IDP with prompt=none if the IDP accepts forwards with prompt=none. + if ("none".equals(context.getAuthenticationSession().getClientNote(OIDCLoginProtocol.PROMPT_PARAM)) && + Boolean.valueOf(idp.get().getConfig().get(ACCEPTS_PROMPT_NONE))) { + context.getAuthenticationSession().setAuthNote(AuthenticationProcessor.FORWARDED_PASSIVE_LOGIN, "true"); + } + LOG.debugf("Redirecting to %s", providerId); + context.forceChallenge(response); + return; } LOG.warnf("Provider not found or not enabled for realm %s", providerId); diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/conditional/ConditionalUserConfiguredAuthenticator.java b/services/src/main/java/org/keycloak/authentication/authenticators/conditional/ConditionalUserConfiguredAuthenticator.java index b5e965b64d..b791f1b262 100644 --- a/services/src/main/java/org/keycloak/authentication/authenticators/conditional/ConditionalUserConfiguredAuthenticator.java +++ b/services/src/main/java/org/keycloak/authentication/authenticators/conditional/ConditionalUserConfiguredAuthenticator.java @@ -1,7 +1,8 @@ package org.keycloak.authentication.authenticators.conditional; -import java.util.ArrayList; +import java.util.LinkedList; import java.util.List; +import java.util.Objects; import org.keycloak.authentication.AuthenticationFlowContext; import org.keycloak.authentication.Authenticator; @@ -20,34 +21,19 @@ public class ConditionalUserConfiguredAuthenticator implements ConditionalAuthen } private boolean matchConditionInFlow(AuthenticationFlowContext context, String flowId) { - List executions = context.getRealm().getAuthenticationExecutions(flowId); - if (executions==null) { - return true; - } - List requiredExecutions = new ArrayList<>(); - List alternativeExecutions = new ArrayList<>(); - executions.forEach(e -> { - //Check if the execution's authenticator is a conditional authenticator, as they must not be evaluated here. - boolean isConditionalAuthenticator = false; - try { - AuthenticatorFactory factory = (AuthenticatorFactory) context.getSession().getKeycloakSessionFactory().getProviderFactory(Authenticator.class, e.getAuthenticator()); - if (factory != null) { - Authenticator auth = factory.create(context.getSession()); - if (auth instanceof ConditionalAuthenticator) { - isConditionalAuthenticator = true; + List requiredExecutions = new LinkedList<>(); + List alternativeExecutions = new LinkedList<>(); + context.getRealm().getAuthenticationExecutionsStream(flowId) + //Check if the execution's authenticator is a conditional authenticator, as they must not be evaluated here. + .filter(e -> isConditionalExecution(context, e)) + .filter(e -> !Objects.equals(context.getExecution().getId(), e.getId()) && !e.isAuthenticatorFlow()) + .forEachOrdered(e -> { + if (e.isRequired()) { + requiredExecutions.add(e); + } else if (e.isAlternative()) { + alternativeExecutions.add(e); } - } - } catch (Exception exception) { - //don't need to catch this - } - if (!context.getExecution().getId().equals(e.getId()) && !e.isAuthenticatorFlow() && !isConditionalAuthenticator) { - if (e.isRequired()) { - requiredExecutions.add(e); - } else if (e.isAlternative()) { - alternativeExecutions.add(e); - } - } - }); + }); if (!requiredExecutions.isEmpty()) { return requiredExecutions.stream().allMatch(e -> isConfiguredFor(e, context)); } else if (!alternativeExecutions.isEmpty()) { @@ -56,6 +42,18 @@ public class ConditionalUserConfiguredAuthenticator implements ConditionalAuthen return true; } + private boolean isConditionalExecution(AuthenticationFlowContext context, AuthenticationExecutionModel e) { + AuthenticatorFactory factory = (AuthenticatorFactory) context.getSession().getKeycloakSessionFactory() + .getProviderFactory(Authenticator.class, e.getAuthenticator()); + if (factory != null) { + Authenticator auth = factory.create(context.getSession()); + if (auth instanceof ConditionalAuthenticator) { + return false; + } + } + return true; + } + private boolean isConfiguredFor(AuthenticationExecutionModel model, AuthenticationFlowContext context) { if (model.isAuthenticatorFlow()) { return matchConditionInFlow(context, model.getId()); diff --git a/services/src/main/java/org/keycloak/credential/UserCredentialStoreManager.java b/services/src/main/java/org/keycloak/credential/UserCredentialStoreManager.java index 377c4e5afd..c837c8b965 100644 --- a/services/src/main/java/org/keycloak/credential/UserCredentialStoreManager.java +++ b/services/src/main/java/org/keycloak/credential/UserCredentialStoreManager.java @@ -25,7 +25,6 @@ import org.keycloak.models.UserModel; import org.keycloak.models.cache.CachedUserModel; import org.keycloak.models.cache.OnUserCache; import org.keycloak.models.cache.UserCache; -import org.keycloak.provider.ProviderFactory; import org.keycloak.storage.StorageId; import org.keycloak.storage.UserStorageManager; import org.keycloak.storage.UserStorageProvider; @@ -36,8 +35,10 @@ import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; +import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; +import java.util.stream.Stream; /** * @author Bill Burke @@ -172,11 +173,9 @@ public class UserCredentialStoreManager implements UserCredentialManager, OnUser if (toValidate.isEmpty()) return true; - List credentialProviders = getCredentialProviders(session, realm, CredentialInputValidator.class); - for (CredentialInputValidator validator : credentialProviders) { - validate(realm, user, toValidate, validator); + getCredentialProviders(session, CredentialInputValidator.class) + .forEach(validator -> validate(realm, user, toValidate, validator)); - } return toValidate.isEmpty(); } @@ -190,14 +189,11 @@ public class UserCredentialStoreManager implements UserCredentialManager, OnUser } } - public static List getCredentialProviders(KeycloakSession session, RealmModel realm, Class type) { - List list = new LinkedList(); - for (ProviderFactory f : session.getKeycloakSessionFactory().getProviderFactories(CredentialProvider.class)) { - if (!Types.supports(type, f, CredentialProviderFactory.class)) continue; - list.add((T) session.getProvider(CredentialProvider.class, f.getId())); - } - return list; - + public static Stream getCredentialProviders(KeycloakSession session, Class type) { + return session.getKeycloakSessionFactory().getProviderFactories(CredentialProvider.class) + .stream() + .filter(f -> Types.supports(type, f, CredentialProviderFactory.class)) + .map(f -> (T) session.getProvider(CredentialProvider.class, f.getId())); } @Override @@ -224,14 +220,9 @@ public class UserCredentialStoreManager implements UserCredentialManager, OnUser } } - List credentialProviders = getCredentialProviders(session, realm, CredentialInputUpdater.class); - for (CredentialInputUpdater updater : credentialProviders) { - if (!updater.supportsCredentialType(input.getType())) continue; - if (updater.updateCredential(realm, user, input)) return true; - - } - - return false; + return getCredentialProviders(session, CredentialInputUpdater.class) + .filter(updater -> updater.supportsCredentialType(input.getType())) + .anyMatch(updater -> updater.updateCredential(realm, user, input)); } @Override @@ -259,14 +250,9 @@ public class UserCredentialStoreManager implements UserCredentialManager, OnUser } - List credentialProviders = getCredentialProviders(session, realm, CredentialInputUpdater.class); - for (CredentialInputUpdater updater : credentialProviders) { - if (!updater.supportsCredentialType(credentialType)) continue; - updater.disableCredentialType(realm, user, credentialType); - - } - - + getCredentialProviders(session, CredentialInputUpdater.class) + .filter(updater -> updater.supportsCredentialType(credentialType)) + .forEach(updater -> updater.disableCredentialType(realm, user, credentialType)); } @Override @@ -291,10 +277,11 @@ public class UserCredentialStoreManager implements UserCredentialManager, OnUser } - List credentialProviders = getCredentialProviders(session, realm, CredentialInputUpdater.class); - for (CredentialInputUpdater updater : credentialProviders) { - types.addAll(updater.getDisableableCredentialTypes(realm, user)); - } + types.addAll(getCredentialProviders(session, CredentialInputUpdater.class) + .map(updater -> updater.getDisableableCredentialTypes(realm, user)) + .flatMap(Set::stream) + .collect(Collectors.toSet())); + return types; } @@ -347,50 +334,38 @@ public class UserCredentialStoreManager implements UserCredentialManager, OnUser @Override public boolean isConfiguredLocally(RealmModel realm, UserModel user, String type) { - List credentialProviders = getCredentialProviders(session, realm, CredentialInputValidator.class); - for (CredentialInputValidator validator : credentialProviders) { - if (validator.supportsCredentialType(type) && validator.isConfiguredFor(realm, user, type)) { - return true; - } - - } - return false; + return getCredentialProviders(session, CredentialInputValidator.class) + .anyMatch(validator -> validator.supportsCredentialType(type) && validator.isConfiguredFor(realm, user, type)); } @Override public CredentialValidationOutput authenticate(KeycloakSession session, RealmModel realm, CredentialInput input) { - List list = UserStorageManager.getEnabledStorageProviders(session, realm, CredentialAuthentication.class); - for (CredentialAuthentication auth : list) { - if (auth.supportsCredentialAuthenticationFor(input.getType())) { - CredentialValidationOutput output = auth.authenticate(realm, input); - if (output != null) return output; - } - } + CredentialValidationOutput output = authenticate( + UserStorageManager.getEnabledStorageProviders(session, realm, CredentialAuthentication.class), + realm, input); - list = getCredentialProviders(session, realm, CredentialAuthentication.class); - for (CredentialAuthentication auth : list) { - if (auth.supportsCredentialAuthenticationFor(input.getType())) { - CredentialValidationOutput output = auth.authenticate(realm, input); - if (output != null) return output; - } - } + return (output != null) ? output : authenticate(getCredentialProviders(session, CredentialAuthentication.class), + realm, input); + } - return null; + public CredentialValidationOutput authenticate(Stream storageProviders, + RealmModel realm, CredentialInput input) { + return storageProviders + .filter(auth -> auth.supportsCredentialAuthenticationFor(input.getType())) + .map(auth -> auth.authenticate(realm, input)) + .filter(Objects::nonNull) + .findFirst() + .orElse(null); } @Override public void onCache(RealmModel realm, CachedUserModel user, UserModel delegate) { - List credentialProviders = getCredentialProviders(session, realm, OnUserCache.class); - for (OnUserCache validator : credentialProviders) { - validator.onCache(realm, user, delegate); - } + getCredentialProviders(session, OnUserCache.class).forEach(validator -> validator.onCache(realm, user, delegate)); } @Override public List getConfiguredUserStorageCredentialTypes(RealmModel realm, UserModel user) { - List credentialProviders = getCredentialProviders(session, realm, CredentialProvider.class); - - return credentialProviders.stream().map(CredentialProvider::getType) + return getCredentialProviders(session, CredentialProvider.class).map(CredentialProvider::getType) .filter(credentialType -> UserStorageCredentialConfigured.CONFIGURED == isConfiguredThroughUserStorage(realm, user, credentialType)) .collect(Collectors.toList()); } diff --git a/services/src/main/java/org/keycloak/exportimport/singlefile/SingleFileExportProvider.java b/services/src/main/java/org/keycloak/exportimport/singlefile/SingleFileExportProvider.java index 9b3aebaff5..987f0fd258 100755 --- a/services/src/main/java/org/keycloak/exportimport/singlefile/SingleFileExportProvider.java +++ b/services/src/main/java/org/keycloak/exportimport/singlefile/SingleFileExportProvider.java @@ -18,6 +18,7 @@ package org.keycloak.exportimport.singlefile; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; import org.jboss.logging.Logger; import org.keycloak.exportimport.ExportProvider; import org.keycloak.exportimport.util.ExportImportSessionTask; @@ -27,13 +28,12 @@ import org.keycloak.models.KeycloakSessionFactory; import org.keycloak.models.RealmModel; import org.keycloak.models.utils.KeycloakModelUtils; import org.keycloak.representations.idm.RealmRepresentation; -import org.keycloak.util.JsonSerialization; +import org.keycloak.services.util.ObjectMapperResolver; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; -import java.util.ArrayList; -import java.util.List; +import java.util.stream.Stream; /** * @author Marek Posolda @@ -59,15 +59,11 @@ public class SingleFileExportProvider implements ExportProvider { @Override protected void runExportImportTask(KeycloakSession session) throws IOException { - List realms = session.realms().getRealms(); - List reps = new ArrayList<>(); - for (RealmModel realm : realms) { - reps.add(ExportUtils.exportRealm(session, realm, true, true)); - } + Stream realms = session.realms().getRealmsStream() + .map(realm -> ExportUtils.exportRealm(session, realm, true, true)); - writeToFile(reps); + writeToFile(realms); } - }); } @@ -92,7 +88,10 @@ public class SingleFileExportProvider implements ExportProvider { } private ObjectMapper getObjectMapper() { - return JsonSerialization.prettyMapper; + ObjectMapper streamSerializer = ObjectMapperResolver.createStreamSerializer(); + streamSerializer.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); + streamSerializer.enable(SerializationFeature.INDENT_OUTPUT); + return streamSerializer; } private void writeToFile(Object reps) throws IOException { 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 34fb971e77..6985ac4f2c 100755 --- a/services/src/main/java/org/keycloak/exportimport/util/ExportUtils.java +++ b/services/src/main/java/org/keycloak/exportimport/util/ExportUtils.java @@ -43,7 +43,6 @@ import org.keycloak.authorization.store.PolicyStore; import org.keycloak.authorization.store.StoreFactory; import org.keycloak.common.Version; import org.keycloak.common.util.MultivaluedHashMap; -import org.keycloak.component.ComponentModel; import org.keycloak.credential.CredentialModel; import org.keycloak.models.ClientModel; import org.keycloak.models.ClientScopeModel; @@ -56,7 +55,6 @@ import org.keycloak.models.UserConsentModel; import org.keycloak.models.UserModel; import org.keycloak.models.utils.ModelToRepresentation; import org.keycloak.representations.idm.ClientRepresentation; -import org.keycloak.representations.idm.ClientScopeRepresentation; import org.keycloak.representations.idm.ComponentExportRepresentation; import org.keycloak.representations.idm.CredentialRepresentation; import org.keycloak.representations.idm.FederatedIdentityRepresentation; @@ -98,23 +96,11 @@ public class ExportUtils { rep.setKeycloakVersion(Version.VERSION_KEYCLOAK); // Client Scopes - List clientScopeModels = realm.getClientScopes(); - List clientScopesReps = new ArrayList<>(); - for (ClientScopeModel app : clientScopeModels) { - ClientScopeRepresentation clientRep = ModelToRepresentation.toRepresentation(app); - clientScopesReps.add(clientRep); - } - rep.setClientScopes(clientScopesReps); - - List defaultClientScopeNames = realm.getDefaultClientScopes(true).stream().map((ClientScopeModel clientScope) -> { - return clientScope.getName(); - }).collect(Collectors.toList()); - rep.setDefaultDefaultClientScopes(defaultClientScopeNames); - - List optionalClientScopeNames = realm.getDefaultClientScopes(false).stream().map((ClientScopeModel clientScope) -> { - return clientScope.getName(); - }).collect(Collectors.toList()); - rep.setDefaultOptionalClientScopes(optionalClientScopeNames); + rep.setClientScopes(realm.getClientScopesStream().map(ModelToRepresentation::toRepresentation).collect(Collectors.toList())); + rep.setDefaultDefaultClientScopes(realm.getDefaultClientScopesStream(true) + .map(ClientScopeModel::getName).collect(Collectors.toList())); + rep.setDefaultOptionalClientScopes(realm.getDefaultClientScopesStream(false) + .map(ClientScopeModel::getName).collect(Collectors.toList())); // Clients List clients = Collections.emptyList(); @@ -199,7 +185,7 @@ public class ExportUtils { } // Scopes of client scopes - for (ClientScopeModel clientScope : realm.getClientScopes()) { + realm.getClientScopesStream().forEach(clientScope -> { Set clientScopes = clientScope.getScopeMappingsStream().collect(Collectors.toSet()); ScopeMappingRepresentation scopeMappingRep = null; for (RoleModel scope : clientScopes) { @@ -232,7 +218,7 @@ public class ExportUtils { currentClientTemplateScope.role(scope.getName()); } } - } + }); if (clientScopeReps.size() > 0) { rep.setClientScopeMappings(clientScopeReps); @@ -285,9 +271,8 @@ public class ExportUtils { } public static MultivaluedHashMap exportComponents(RealmModel realm, String parentId) { - List componentList = realm.getComponents(parentId); MultivaluedHashMap components = new MultivaluedHashMap<>(); - for (ComponentModel component : componentList) { + realm.getComponentsStream(parentId).forEach(component -> { ComponentExportRepresentation compRep = new ComponentExportRepresentation(); compRep.setId(component.getId()); compRep.setProviderId(component.getProviderId()); @@ -296,7 +281,7 @@ public class ExportUtils { compRep.setSubType(component.getSubType()); compRep.setSubComponents(exportComponents(realm, component.getId())); components.add(component.getProviderType(), compRep); - } + }); return components; } diff --git a/services/src/main/java/org/keycloak/exportimport/util/ImportUtils.java b/services/src/main/java/org/keycloak/exportimport/util/ImportUtils.java index c86c7815ba..62c8fdaede 100755 --- a/services/src/main/java/org/keycloak/exportimport/util/ImportUtils.java +++ b/services/src/main/java/org/keycloak/exportimport/util/ImportUtils.java @@ -68,12 +68,12 @@ public class ImportUtils { // If master was imported, we may need to re-create realm management clients if (masterImported) { - for (RealmModel realm : session.realms().getRealms()) { - if (realm.getMasterAdminClient() == null) { - logger.infof("Re-created management client in master realm for realm '%s'", realm.getName()); - new RealmManager(session).setupMasterAdminManagement(realm); - } - } + session.realms().getRealmsStream() + .filter(realm -> realm.getMasterAdminClient() == null) + .forEach(realm -> { + logger.infof("Re-created management client in master realm for realm '%s'", realm.getName()); + new RealmManager(session).setupMasterAdminManagement(realm); + }); } } @@ -99,9 +99,7 @@ public class ImportUtils { logger.infof("Realm '%s' already exists. Removing it before import", realmName); if (Config.getAdminRealm().equals(realm.getId())) { // Delete all masterAdmin apps due to foreign key constraints - for (RealmModel currRealm : model.getRealms()) { - currRealm.setMasterAdminClient(null); - } + model.getRealmsStream().forEach(r -> r.setMasterAdminClient(null)); } // TODO: For migration between versions, it should be possible to delete just realm but keep it's users model.removeRealm(realm.getId()); diff --git a/services/src/main/java/org/keycloak/exportimport/util/MultipleStepsExportProvider.java b/services/src/main/java/org/keycloak/exportimport/util/MultipleStepsExportProvider.java index 851abe28e9..5008064675 100755 --- a/services/src/main/java/org/keycloak/exportimport/util/MultipleStepsExportProvider.java +++ b/services/src/main/java/org/keycloak/exportimport/util/MultipleStepsExportProvider.java @@ -31,6 +31,7 @@ import org.keycloak.representations.idm.RealmRepresentation; import java.io.IOException; import java.util.List; +import java.util.stream.Collectors; /** * @author Marek Posolda @@ -47,7 +48,7 @@ public abstract class MultipleStepsExportProvider implements ExportProvider { @Override public void run(KeycloakSession session) { - List realms = session.realms().getRealms(); + List realms = session.realms().getRealmsStream().collect(Collectors.toList()); holder.realms = realms; } diff --git a/services/src/main/java/org/keycloak/forms/account/freemarker/model/AccountFederatedIdentityBean.java b/services/src/main/java/org/keycloak/forms/account/freemarker/model/AccountFederatedIdentityBean.java index 0b597f3636..1842c392e0 100755 --- a/services/src/main/java/org/keycloak/forms/account/freemarker/model/AccountFederatedIdentityBean.java +++ b/services/src/main/java/org/keycloak/forms/account/freemarker/model/AccountFederatedIdentityBean.java @@ -27,9 +27,10 @@ import org.keycloak.models.utils.KeycloakModelUtils; import org.keycloak.services.resources.account.AccountFormService; import java.net.URI; -import java.util.ArrayList; import java.util.List; import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; /** * @author Marek Posolda @@ -39,41 +40,36 @@ public class AccountFederatedIdentityBean { private static OrderedModel.OrderedModelComparator IDP_COMPARATOR_INSTANCE = new OrderedModel.OrderedModelComparator<>(); - private final List identities = new ArrayList<>(); + private final List identities; private final boolean removeLinkPossible; private final KeycloakSession session; public AccountFederatedIdentityBean(KeycloakSession session, RealmModel realm, UserModel user, URI baseUri, String stateChecker) { this.session = session; - List identityProviders = realm.getIdentityProviders(); Set identities = session.users().getFederatedIdentities(user, realm); - int availableIdentities = 0; - if (identityProviders != null && !identityProviders.isEmpty()) { - for (IdentityProviderModel provider : identityProviders) { - if (!provider.isEnabled()) { - continue; - } - String providerId = provider.getAlias(); + AtomicInteger availableIdentities = new AtomicInteger(0); + this.identities = realm.getIdentityProvidersStream() + .filter(IdentityProviderModel::isEnabled) + .map(provider -> { + String providerId = provider.getAlias(); - FederatedIdentityModel identity = getIdentity(identities, providerId); + FederatedIdentityModel identity = getIdentity(identities, providerId); - if (identity != null) { - availableIdentities++; - } + if (identity != null) { + availableIdentities.getAndIncrement(); + } - String displayName = KeycloakModelUtils.getIdentityProviderDisplayName(session, provider); - FederatedIdentityEntry entry = new FederatedIdentityEntry(identity, displayName, provider.getAlias(), provider.getAlias(), - provider.getConfig() != null ? provider.getConfig().get("guiOrder") : null); - this.identities.add(entry); - } - } - - this.identities.sort(IDP_COMPARATOR_INSTANCE); + String displayName = KeycloakModelUtils.getIdentityProviderDisplayName(session, provider); + return new FederatedIdentityEntry(identity, displayName, provider.getAlias(), provider.getAlias(), + provider.getConfig() != null ? provider.getConfig().get("guiOrder") : null); + }) + .sorted(IDP_COMPARATOR_INSTANCE) + .collect(Collectors.toList()); // Removing last social provider is not possible if you don't have other possibility to authenticate - this.removeLinkPossible = availableIdentities > 1 || user.getFederationLink() != null || AccountFormService.isPasswordSet(session, realm, user); + this.removeLinkPossible = availableIdentities.get() > 1 || user.getFederationLink() != null || AccountFormService.isPasswordSet(session, realm, user); } private FederatedIdentityModel getIdentity(Set identities, String providerId) { diff --git a/services/src/main/java/org/keycloak/forms/account/freemarker/model/RealmBean.java b/services/src/main/java/org/keycloak/forms/account/freemarker/model/RealmBean.java index a0407aae90..f79ca94153 100755 --- a/services/src/main/java/org/keycloak/forms/account/freemarker/model/RealmBean.java +++ b/services/src/main/java/org/keycloak/forms/account/freemarker/model/RealmBean.java @@ -19,6 +19,7 @@ package org.keycloak.forms.account.freemarker.model; import org.keycloak.models.RealmModel; import java.util.Set; +import java.util.stream.Collectors; /** * @author Michael Gerber @@ -58,7 +59,7 @@ public class RealmBean { } public Set getSupportedLocales(){ - return realm.getSupportedLocales(); + return realm.getSupportedLocalesStream().collect(Collectors.toSet()); } public boolean isEditUsernameAllowed() { diff --git a/services/src/main/java/org/keycloak/forms/login/freemarker/FreeMarkerLoginFormsProvider.java b/services/src/main/java/org/keycloak/forms/login/freemarker/FreeMarkerLoginFormsProvider.java index 251cd7a997..2d5987237d 100755 --- a/services/src/main/java/org/keycloak/forms/login/freemarker/FreeMarkerLoginFormsProvider.java +++ b/services/src/main/java/org/keycloak/forms/login/freemarker/FreeMarkerLoginFormsProvider.java @@ -398,8 +398,8 @@ public class FreeMarkerLoginFormsProvider implements LoginFormsProvider { if (realm != null) { attributes.put("realm", new RealmBean(realm)); - List identityProviders = realm.getIdentityProviders(); - identityProviders = LoginFormsUtil.filterIdentityProviders(identityProviders, session, realm, attributes, formData, context); + List identityProviders = LoginFormsUtil + .filterIdentityProviders(realm.getIdentityProvidersStream(), session, context); attributes.put("social", new IdentityProviderBean(realm, session, identityProviders, baseUriWithCodeAndClientId)); attributes.put("url", new UrlBean(realm, theme, baseUri, this.actionUri)); diff --git a/services/src/main/java/org/keycloak/forms/login/freemarker/LoginFormsUtil.java b/services/src/main/java/org/keycloak/forms/login/freemarker/LoginFormsUtil.java index d347c7262d..88d0c0d0a6 100755 --- a/services/src/main/java/org/keycloak/forms/login/freemarker/LoginFormsUtil.java +++ b/services/src/main/java/org/keycloak/forms/login/freemarker/LoginFormsUtil.java @@ -36,6 +36,7 @@ import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; +import java.util.stream.Stream; /** * Various util methods, so the logic is not hardcoded in freemarker beans @@ -78,8 +79,7 @@ public class LoginFormsUtil { } } - public static List filterIdentityProviders(List providers, KeycloakSession session, RealmModel realm, - Map attributes, MultivaluedMap formData, AuthenticationFlowContext context) { + public static List filterIdentityProviders(Stream providers, KeycloakSession session, AuthenticationFlowContext context) { if (context != null) { AuthenticationSessionModel authSession = context.getAuthenticationSession(); @@ -87,11 +87,11 @@ public class LoginFormsUtil { if (serializedCtx != null) { IdentityProviderModel idp = serializedCtx.deserialize(session, authSession).getIdpConfig(); - return providers.stream() + return providers .filter(p -> !Objects.equals(p.getAlias(), idp.getAlias())) .collect(Collectors.toList()); } } - return providers; + return providers.collect(Collectors.toList()); } } diff --git a/services/src/main/java/org/keycloak/forms/login/freemarker/model/RealmBean.java b/services/src/main/java/org/keycloak/forms/login/freemarker/model/RealmBean.java index cd6156861e..06364c2c8d 100755 --- a/services/src/main/java/org/keycloak/forms/login/freemarker/model/RealmBean.java +++ b/services/src/main/java/org/keycloak/forms/login/freemarker/model/RealmBean.java @@ -17,9 +17,10 @@ package org.keycloak.forms.login.freemarker.model; import org.keycloak.models.RealmModel; -import org.keycloak.models.RequiredCredentialModel; import org.keycloak.representations.idm.CredentialRepresentation; +import java.util.Objects; + /** * @author Stian Thorgersen */ @@ -86,12 +87,8 @@ public class RealmBean { } public boolean isPassword() { - for (RequiredCredentialModel r : realm.getRequiredCredentials()) { - if (r.getType().equals(CredentialRepresentation.PASSWORD)) { - return true; - } - } - return false; + return realm.getRequiredCredentialsStream() + .anyMatch(r -> Objects.equals(r.getType(), CredentialRepresentation.PASSWORD)); } } diff --git a/services/src/main/java/org/keycloak/keys/DefaultKeyManager.java b/services/src/main/java/org/keycloak/keys/DefaultKeyManager.java index 286f26e7bb..b206c607e6 100644 --- a/services/src/main/java/org/keycloak/keys/DefaultKeyManager.java +++ b/services/src/main/java/org/keycloak/keys/DefaultKeyManager.java @@ -31,11 +31,8 @@ import javax.crypto.SecretKey; import java.security.PrivateKey; import java.security.PublicKey; import java.security.cert.Certificate; -import java.util.Comparator; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; +import java.util.*; +import java.util.stream.Collectors; /** * @author Stian Thorgersen @@ -246,22 +243,22 @@ public class DefaultKeyManager implements KeyManager { private List getProviders(RealmModel realm) { List providers = providersMap.get(realm.getId()); if (providers == null) { - providers = new LinkedList<>(); - - List components = new LinkedList<>(realm.getComponents(realm.getId(), KeyProvider.class.getName())); - components.sort(new ProviderComparator()); - - for (ComponentModel c : components) { - try { - ProviderFactory f = session.getKeycloakSessionFactory().getProviderFactory(KeyProvider.class, c.getProviderId()); - KeyProviderFactory factory = (KeyProviderFactory) f; - KeyProvider provider = factory.create(session, c); - session.enlistForClose(provider); - providers.add(provider); - } catch (Throwable t) { - logger.errorv(t, "Failed to load provider {0}", c.getId()); - } - } + providers = realm.getComponentsStream(realm.getId(), KeyProvider.class.getName()) + .sorted(new ProviderComparator()) + .map(c -> { + try { + ProviderFactory f = session.getKeycloakSessionFactory().getProviderFactory(KeyProvider.class, c.getProviderId()); + KeyProviderFactory factory = (KeyProviderFactory) f; + KeyProvider provider = factory.create(session, c); + session.enlistForClose(provider); + return provider; + } catch (Throwable t) { + logger.errorv(t, "Failed to load provider {0}", c.getId()); + return null; + } + }) + .filter(Objects::nonNull) + .collect(Collectors.toList()); providersMap.put(realm.getId(), providers); } diff --git a/services/src/main/java/org/keycloak/locale/DefaultLocaleSelectorProvider.java b/services/src/main/java/org/keycloak/locale/DefaultLocaleSelectorProvider.java index 1b435ddd28..4b330c7383 100644 --- a/services/src/main/java/org/keycloak/locale/DefaultLocaleSelectorProvider.java +++ b/services/src/main/java/org/keycloak/locale/DefaultLocaleSelectorProvider.java @@ -20,17 +20,13 @@ import org.jboss.logging.Logger; import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; import org.keycloak.models.UserModel; -import org.keycloak.services.managers.AuthenticationManager; -import org.keycloak.services.util.CookieHelper; import org.keycloak.sessions.AuthenticationSessionModel; -import org.keycloak.storage.ReadOnlyException; import javax.ws.rs.core.Cookie; import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.UriInfo; import java.util.List; import java.util.Locale; -import java.util.Set; +import java.util.stream.Collectors; public class DefaultLocaleSelectorProvider implements LocaleSelectorProvider { @@ -168,19 +164,19 @@ public class DefaultLocaleSelectorProvider implements LocaleSelectorProvider { } private Locale findLocale(RealmModel realm, String... localeStrings) { - Set supportedLocales = realm.getSupportedLocales(); + List supportedLocales = realm.getSupportedLocalesStream() + .map(Locale::forLanguageTag).collect(Collectors.toList()); for (String localeString : localeStrings) { if (localeString != null) { Locale result = null; Locale search = Locale.forLanguageTag(localeString); - for (String languageTag : supportedLocales) { - Locale locale = Locale.forLanguageTag(languageTag); - if (locale.getLanguage().equals(search.getLanguage())) { - if (search.getCountry().equals("") ^ locale.getCountry().equals("") && result == null) { - result = locale; + for (Locale supportedLocale : supportedLocales) { + if (supportedLocale.getLanguage().equals(search.getLanguage())) { + if (search.getCountry().equals("") ^ supportedLocale.getCountry().equals("") && result == null) { + result = supportedLocale; } - if (locale.getCountry().equals(search.getCountry())) { - return locale; + if (supportedLocale.getCountry().equals(search.getCountry())) { + return supportedLocale; } } } diff --git a/services/src/main/java/org/keycloak/protocol/oidc/OIDCWellKnownProvider.java b/services/src/main/java/org/keycloak/protocol/oidc/OIDCWellKnownProvider.java index bbf94d0053..6f1eeb02e1 100755 --- a/services/src/main/java/org/keycloak/protocol/oidc/OIDCWellKnownProvider.java +++ b/services/src/main/java/org/keycloak/protocol/oidc/OIDCWellKnownProvider.java @@ -47,6 +47,8 @@ import java.net.URI; import java.util.Arrays; import java.util.LinkedList; import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; /** * @author Stian Thorgersen @@ -119,13 +121,10 @@ public class OIDCWellKnownProvider implements WellKnownProvider { config.setClaimTypesSupported(DEFAULT_CLAIM_TYPES_SUPPORTED); config.setClaimsParameterSupported(true); - List scopes = realm.getClientScopes(); - List scopeNames = new LinkedList<>(); - for (ClientScopeModel clientScope : scopes) { - if (OIDCLoginProtocol.LOGIN_PROTOCOL.equals(clientScope.getProtocol())) { - scopeNames.add(clientScope.getName()); - } - } + List scopeNames = realm.getClientScopesStream() + .filter(clientScope -> Objects.equals(OIDCLoginProtocol.LOGIN_PROTOCOL, clientScope.getProtocol())) + .map(ClientScopeModel::getName) + .collect(Collectors.toList()); scopeNames.add(0, OAuth2Constants.SCOPE_OPENID); config.setScopesSupported(scopeNames); diff --git a/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java b/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java index 942aac256d..436e3f8743 100755 --- a/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java +++ b/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java @@ -25,8 +25,6 @@ import org.keycloak.TokenCategory; import org.keycloak.TokenVerifier; import org.keycloak.broker.oidc.OIDCIdentityProvider; import org.keycloak.broker.provider.IdentityBrokerException; -import org.keycloak.broker.provider.IdentityProvider; -import org.keycloak.broker.provider.IdentityProviderFactory; import org.keycloak.cluster.ClusterProvider; import org.keycloak.common.ClientConnection; import org.keycloak.common.VerificationException; @@ -44,7 +42,6 @@ import org.keycloak.models.AuthenticatedClientSessionModel; import org.keycloak.models.ClientModel; import org.keycloak.models.ClientScopeModel; import org.keycloak.models.ClientSessionContext; -import org.keycloak.models.IdentityProviderModel; import org.keycloak.models.KeycloakSession; import org.keycloak.models.ProtocolMapperModel; import org.keycloak.models.RealmModel; @@ -78,7 +75,6 @@ import org.keycloak.services.util.MtlsHoKTokenUtil; import org.keycloak.sessions.AuthenticationSessionModel; import org.keycloak.util.TokenUtil; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; @@ -1092,13 +1088,14 @@ public class TokenManager { } LogoutToken logoutToken = logoutTokenOptional.get(); - List identityProviders = getOIDCIdentityProviders(realm, session); + List identityProviders = getOIDCIdentityProviders(realm, session).collect(Collectors.toList()); if (identityProviders.isEmpty()) { return LogoutTokenValidationCode.COULD_NOT_FIND_IDP; } - List validOidcIdentityProviders = validateLogoutTokenAgainstIdpProvider(identityProviders, encodedLogoutToken, logoutToken); - if (validOidcIdentityProviders.isEmpty()) { + Stream validOidcIdentityProviders = + validateLogoutTokenAgainstIdpProvider(identityProviders.stream(), encodedLogoutToken, logoutToken); + if (validOidcIdentityProviders.count() == 0) { return LogoutTokenValidationCode.TOKEN_VERIFICATION_WITH_IDP_FAILED; } @@ -1135,43 +1132,37 @@ public class TokenManager { } - public List getValidOIDCIdentityProvidersForBackchannelLogout(RealmModel realm, KeycloakSession session, String encodedLogoutToken, LogoutToken logoutToken) { - List identityProviders = getOIDCIdentityProviders(realm, session); - return validateLogoutTokenAgainstIdpProvider(identityProviders, encodedLogoutToken, logoutToken); + public Stream getValidOIDCIdentityProvidersForBackchannelLogout(RealmModel realm, KeycloakSession session, String encodedLogoutToken, LogoutToken logoutToken) { + return validateLogoutTokenAgainstIdpProvider(getOIDCIdentityProviders(realm, session), encodedLogoutToken, logoutToken); } - public List validateLogoutTokenAgainstIdpProvider(List oidcIdps, String encodedLogoutToken, LogoutToken logoutToken) { - List validIdps = new ArrayList<>(); - for (OIDCIdentityProvider oidcIdp : oidcIdps) { - if (oidcIdp.getConfig().getIssuer() != null) { - if (oidcIdp.isIssuer(logoutToken.getIssuer(), null)) { - try { - oidcIdp.validateToken(encodedLogoutToken); - validIdps.add(oidcIdp); - } catch (IdentityBrokerException e) { - logger.debugf("LogoutToken verification with identity provider failed", e.getMessage()); - } - } - } - } - return validIdps; + public Stream validateLogoutTokenAgainstIdpProvider(Stream oidcIdps, String encodedLogoutToken, LogoutToken logoutToken) { + return oidcIdps + .filter(oidcIdp -> oidcIdp.getConfig().getIssuer() != null) + .filter(oidcIdp -> oidcIdp.isIssuer(logoutToken.getIssuer(), null)) + .filter(oidcIdp -> { + try { + oidcIdp.validateToken(encodedLogoutToken); + return true; + } catch (IdentityBrokerException e) { + logger.debugf("LogoutToken verification with identity provider failed", e.getMessage()); + return false; + } + }); } - private List getOIDCIdentityProviders(RealmModel realm, KeycloakSession session) { - List availableProviders = new ArrayList<>(); + private Stream getOIDCIdentityProviders(RealmModel realm, KeycloakSession session) { try { - for (IdentityProviderModel idpModel : realm.getIdentityProviders()) { - IdentityProviderFactory factory = IdentityBrokerService.getIdentityProviderFactory(session, idpModel); - IdentityProvider identityProvider = factory.create(session, idpModel); - if (identityProvider instanceof OIDCIdentityProvider) { - availableProviders.add(((OIDCIdentityProvider) identityProvider)); - } - } + return realm.getIdentityProvidersStream() + .map(idpModel -> + IdentityBrokerService.getIdentityProviderFactory(session, idpModel).create(session, idpModel)) + .filter(OIDCIdentityProvider.class::isInstance) + .map(OIDCIdentityProvider.class::cast); } catch (IdentityBrokerException e) { logger.warnf("LogoutToken verification with identity provider failed", e.getMessage()); } - return availableProviders; + return Stream.empty(); } private boolean checkLogoutTokenForEvents(LogoutToken logoutToken) { diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/LogoutEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/LogoutEndpoint.java index 6ba707a717..f61acc9e80 100755 --- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/LogoutEndpoint.java +++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/LogoutEndpoint.java @@ -46,7 +46,6 @@ import org.keycloak.representations.RefreshToken; import org.keycloak.services.ErrorPage; import org.keycloak.services.ErrorResponseException; import org.keycloak.services.clientpolicy.ClientPolicyException; -import org.keycloak.services.clientpolicy.DefaultClientPolicyManager; import org.keycloak.services.clientpolicy.LogoutRequestContext; import org.keycloak.services.managers.AuthenticationManager; import org.keycloak.services.managers.UserSessionManager; @@ -63,7 +62,8 @@ import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriBuilder; import java.util.List; -import java.util.stream.Collectors; +import java.util.concurrent.atomic.AtomicReference; +import java.util.stream.Stream; /** * @author Stian Thorgersen @@ -270,10 +270,9 @@ public class LogoutEndpoint { LogoutToken logoutToken = tokenManager.toLogoutToken(encodedLogoutToken).get(); - List identityProviderAliases = tokenManager.getValidOIDCIdentityProvidersForBackchannelLogout(realm, - session, encodedLogoutToken, logoutToken).stream() - .map(idp -> idp.getConfig().getAlias()) - .collect(Collectors.toList()); + Stream identityProviderAliases = tokenManager.getValidOIDCIdentityProvidersForBackchannelLogout(realm, + session, encodedLogoutToken, logoutToken) + .map(idp -> idp.getConfig().getAlias()); boolean logoutOfflineSessions = Boolean.parseBoolean(logoutToken.getEvents() .getOrDefault(TokenUtil.TOKEN_BACKCHANNEL_LOGOUT_EVENT_REVOKE_OFFLINE_TOKENS, false).toString()); @@ -313,10 +312,10 @@ public class LogoutEndpoint { } private BackchannelLogoutResponse backchannelLogoutWithSessionId(String sessionId, - List identityProviderAliases, boolean logoutOfflineSessions) { - BackchannelLogoutResponse backchannelLogoutResponse = new BackchannelLogoutResponse(); - backchannelLogoutResponse.setLocalLogoutSucceeded(true); - for (String identityProviderAlias : identityProviderAliases) { + Stream identityProviderAliases, boolean logoutOfflineSessions) { + AtomicReference backchannelLogoutResponse = new AtomicReference<>(new BackchannelLogoutResponse()); + backchannelLogoutResponse.get().setLocalLogoutSucceeded(true); + identityProviderAliases.forEach(identityProviderAlias -> { UserSessionModel userSession = session.sessions().getUserSessionByBrokerSessionId(realm, identityProviderAlias + "." + sessionId); @@ -325,11 +324,11 @@ public class LogoutEndpoint { } if (userSession != null) { - backchannelLogoutResponse = logoutUserSession(userSession); + backchannelLogoutResponse.set(logoutUserSession(userSession)); } - } + }); - return backchannelLogoutResponse; + return backchannelLogoutResponse.get(); } private void logoutOfflineUserSession(String brokerSessionId) { @@ -341,10 +340,11 @@ public class LogoutEndpoint { } private BackchannelLogoutResponse backchannelLogoutFederatedUserId(String federatedUserId, - List identityProviderAliases, boolean logoutOfflineSessions) { + Stream identityProviderAliases, + boolean logoutOfflineSessions) { BackchannelLogoutResponse backchannelLogoutResponse = new BackchannelLogoutResponse(); backchannelLogoutResponse.setLocalLogoutSucceeded(true); - for (String identityProviderAlias : identityProviderAliases) { + identityProviderAliases.forEach(identityProviderAlias -> { List userSessions = session.sessions().getUserSessionByBrokerUserId(realm, identityProviderAlias + "." + federatedUserId); @@ -360,7 +360,7 @@ public class LogoutEndpoint { userBackchannelLogoutResponse.getClientResponses() .forEach(backchannelLogoutResponse::addClientResponses); } - } + }); return backchannelLogoutResponse; } diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenEndpoint.java index 8163db916e..6f50dc8351 100644 --- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenEndpoint.java +++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenEndpoint.java @@ -127,8 +127,10 @@ import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; +import java.util.concurrent.atomic.AtomicReference; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.stream.Collectors; import static org.keycloak.models.ImpersonationSessionNote.IMPERSONATOR_ID; import static org.keycloak.models.ImpersonationSessionNote.IMPERSONATOR_USERNAME; @@ -1051,33 +1053,34 @@ public class TokenEndpoint { } public Response exchangeExternalToken(String issuer, String subjectToken) { - ExchangeExternalToken externalIdp = null; - IdentityProviderModel externalIdpModel = null; + AtomicReference externalIdp = new AtomicReference<>(null); + AtomicReference externalIdpModel = new AtomicReference<>(null); - for (IdentityProviderModel idpModel : realm.getIdentityProviders()) { + realm.getIdentityProvidersStream().filter(idpModel -> { IdentityProviderFactory factory = IdentityBrokerService.getIdentityProviderFactory(session, idpModel); IdentityProvider idp = factory.create(session, idpModel); if (idp instanceof ExchangeExternalToken) { ExchangeExternalToken external = (ExchangeExternalToken) idp; if (idpModel.getAlias().equals(issuer) || external.isIssuer(issuer, formParams)) { - externalIdp = external; - externalIdpModel = idpModel; - break; + externalIdp.set(external); + externalIdpModel.set(idpModel); + return true; } } - } + return false; + }).findFirst(); - if (externalIdp == null) { + if (externalIdp.get() == null) { event.error(Errors.INVALID_ISSUER); throw new CorsErrorResponseException(cors, Errors.INVALID_ISSUER, "Invalid " + OAuth2Constants.SUBJECT_ISSUER + " parameter", Response.Status.BAD_REQUEST); } - if (!AdminPermissions.management(session, realm).idps().canExchangeTo(client, externalIdpModel)) { + if (!AdminPermissions.management(session, realm).idps().canExchangeTo(client, externalIdpModel.get())) { event.detail(Details.REASON, "client not allowed to exchange subject_issuer"); event.error(Errors.NOT_ALLOWED); throw new CorsErrorResponseException(cors, OAuthErrorException.ACCESS_DENIED, "Client not allowed to exchange", Response.Status.FORBIDDEN); } - BrokeredIdentityContext context = externalIdp.exchangeExternal(event, formParams); + BrokeredIdentityContext context = externalIdp.get().exchangeExternal(event, formParams); if (context == null) { event.error(Errors.INVALID_ISSUER); throw new CorsErrorResponseException(cors, Errors.INVALID_ISSUER, "Invalid " + OAuth2Constants.SUBJECT_ISSUER + " parameter", Response.Status.BAD_REQUEST); @@ -1086,10 +1089,10 @@ public class TokenEndpoint { UserModel user = importUserFromExternalIdentity(context); UserSessionModel userSession = session.sessions().createUserSession(realm, user, user.getUsername(), clientConnection.getRemoteAddr(), "external-exchange", false, null, null); - externalIdp.exchangeExternalComplete(userSession, context, formParams); + externalIdp.get().exchangeExternalComplete(userSession, context, formParams); // this must exist so that we can obtain access token from user session if idp's store tokens is off - userSession.setNote(IdentityProvider.EXTERNAL_IDENTITY_PROVIDER, externalIdpModel.getAlias()); + userSession.setNote(IdentityProvider.EXTERNAL_IDENTITY_PROVIDER, externalIdpModel.get().getAlias()); userSession.setNote(IdentityProvider.FEDERATED_ACCESS_TOKEN, subjectToken); return exchangeClientToClient(user, userSession); @@ -1106,13 +1109,12 @@ public class TokenEndpoint { //session.getContext().setClient(authenticationSession.getClient()); context.getIdp().preprocessFederatedIdentity(session, realm, context); - Set mappers = realm.getIdentityProviderMappersByAlias(context.getIdpConfig().getAlias()); - if (mappers != null) { - KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory(); - for (IdentityProviderMapperModel mapper : mappers) { - IdentityProviderMapper target = (IdentityProviderMapper)sessionFactory.getProviderFactory(IdentityProviderMapper.class, mapper.getIdentityProviderMapper()); - target.preprocessFederatedIdentity(session, realm, mapper, context); - } + Set mappers = realm.getIdentityProviderMappersByAliasStream(context.getIdpConfig().getAlias()) + .collect(Collectors.toSet()); + KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory(); + for (IdentityProviderMapperModel mapper : mappers) { + IdentityProviderMapper target = (IdentityProviderMapper)sessionFactory.getProviderFactory(IdentityProviderMapper.class, mapper.getIdentityProviderMapper()); + target.preprocessFederatedIdentity(session, realm, mapper, context); } FederatedIdentityModel federatedIdentityModel = new FederatedIdentityModel(providerId, context.getId(), @@ -1163,12 +1165,10 @@ public class TokenEndpoint { session.users().addFederatedIdentity(realm, user, federatedIdentityModel); context.getIdp().importNewUser(session, realm, user, context); - if (mappers != null) { - KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory(); - for (IdentityProviderMapperModel mapper : mappers) { - IdentityProviderMapper target = (IdentityProviderMapper)sessionFactory.getProviderFactory(IdentityProviderMapper.class, mapper.getIdentityProviderMapper()); - target.importNewUser(session, realm, user, mapper, context); - } + + for (IdentityProviderMapperModel mapper : mappers) { + IdentityProviderMapper target = (IdentityProviderMapper)sessionFactory.getProviderFactory(IdentityProviderMapper.class, mapper.getIdentityProviderMapper()); + target.importNewUser(session, realm, user, mapper, context); } if (context.getIdpConfig().isTrustEmail() && !Validation.isBlank(user.getEmail())) { @@ -1188,12 +1188,10 @@ public class TokenEndpoint { } context.getIdp().updateBrokeredUser(session, realm, user, context); - if (mappers != null) { - KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory(); - for (IdentityProviderMapperModel mapper : mappers) { - IdentityProviderMapper target = (IdentityProviderMapper)sessionFactory.getProviderFactory(IdentityProviderMapper.class, mapper.getIdentityProviderMapper()); - IdentityProviderMapperSyncModeDelegate.delegateUpdateBrokeredUser(session, realm, user, mapper, context, target); - } + + for (IdentityProviderMapperModel mapper : mappers) { + IdentityProviderMapper target = (IdentityProviderMapper)sessionFactory.getProviderFactory(IdentityProviderMapper.class, mapper.getIdentityProviderMapper()); + IdentityProviderMapperSyncModeDelegate.delegateUpdateBrokeredUser(session, realm, user, mapper, context, target); } } return user; diff --git a/services/src/main/java/org/keycloak/protocol/oidc/installation/KeycloakOIDCClientInstallation.java b/services/src/main/java/org/keycloak/protocol/oidc/installation/KeycloakOIDCClientInstallation.java index 49020ff557..57f6b7c2e1 100755 --- a/services/src/main/java/org/keycloak/protocol/oidc/installation/KeycloakOIDCClientInstallation.java +++ b/services/src/main/java/org/keycloak/protocol/oidc/installation/KeycloakOIDCClientInstallation.java @@ -22,7 +22,6 @@ import org.keycloak.authentication.ClientAuthenticator; import org.keycloak.authentication.ClientAuthenticatorFactory; import org.keycloak.authorization.admin.AuthorizationService; import org.keycloak.models.ClientModel; -import org.keycloak.models.ClientScopeModel; import org.keycloak.models.Constants; import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSessionFactory; @@ -111,15 +110,15 @@ public class KeycloakOIDCClientInstallation implements ClientInstallationProvide // Check if there is client scope with audience protocol mapper created for particular client. If yes, admin wants verifying token audience String clientId = client.getClientId(); - for (ClientScopeModel clientScope : client.getRealm().getClientScopes()) { + return client.getRealm().getClientScopesStream().anyMatch(clientScope -> { for (ProtocolMapperModel protocolMapper : clientScope.getProtocolMappers()) { - if (AudienceProtocolMapper.PROVIDER_ID.equals(protocolMapper.getProtocolMapper()) && (clientId.equals(protocolMapper.getConfig().get(AudienceProtocolMapper.INCLUDED_CLIENT_AUDIENCE)))) { + if (AudienceProtocolMapper.PROVIDER_ID.equals(protocolMapper.getProtocolMapper()) && + (clientId.equals(protocolMapper.getConfig().get(AudienceProtocolMapper.INCLUDED_CLIENT_AUDIENCE)))) { return true; } } - } - - return false; + return false; + }); } diff --git a/services/src/main/java/org/keycloak/protocol/saml/profile/ecp/SamlEcpProfileService.java b/services/src/main/java/org/keycloak/protocol/saml/profile/ecp/SamlEcpProfileService.java index eac5d9809d..dd4027f2ec 100755 --- a/services/src/main/java/org/keycloak/protocol/saml/profile/ecp/SamlEcpProfileService.java +++ b/services/src/main/java/org/keycloak/protocol/saml/profile/ecp/SamlEcpProfileService.java @@ -45,6 +45,7 @@ import javax.xml.soap.SOAPHeaderElement; import java.io.IOException; import java.io.InputStream; import java.util.Map; +import java.util.Objects; /** * @author Pedro Igor @@ -149,12 +150,9 @@ public class SamlEcpProfileService extends SamlService { @Override protected AuthenticationFlowModel getAuthenticationFlow(AuthenticationSessionModel authSession) { - for (AuthenticationFlowModel flowModel : realm.getAuthenticationFlows()) { - if (flowModel.getAlias().equals(DefaultAuthenticationFlows.SAML_ECP_FLOW)) { - return flowModel; - } - } - - throw new RuntimeException("Could not resolve authentication flow for SAML ECP Profile."); + return realm.getAuthenticationFlowsStream() + .filter(flow -> Objects.equals(flow.getAlias(), DefaultAuthenticationFlows.SAML_ECP_FLOW)) + .findFirst() + .orElseThrow(() -> new RuntimeException("Could not resolve authentication flow for SAML ECP Profile.")); } } diff --git a/services/src/main/java/org/keycloak/services/clientpolicy/DefaultClientPolicyManager.java b/services/src/main/java/org/keycloak/services/clientpolicy/DefaultClientPolicyManager.java index 8f55e9f2c8..f03a10cdc1 100644 --- a/services/src/main/java/org/keycloak/services/clientpolicy/DefaultClientPolicyManager.java +++ b/services/src/main/java/org/keycloak/services/clientpolicy/DefaultClientPolicyManager.java @@ -17,20 +17,13 @@ package org.keycloak.services.clientpolicy; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; +import java.util.*; +import java.util.stream.Collectors; import org.jboss.logging.Logger; import org.keycloak.common.Profile; -import org.keycloak.component.ComponentModel; import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; -import org.keycloak.services.clientpolicy.ClientPolicyContext; -import org.keycloak.services.clientpolicy.ClientPolicyException; -import org.keycloak.services.clientpolicy.ClientPolicyManager; -import org.keycloak.services.clientpolicy.ClientPolicyProvider; import org.keycloak.services.clientpolicy.condition.ClientPolicyConditionProvider; import org.keycloak.services.clientpolicy.executor.ClientPolicyExecutorProvider; @@ -67,18 +60,20 @@ public class DefaultClientPolicyManager implements ClientPolicyManager { private List getProviders(RealmModel realm) { List providers = providersMap.get(realm.getId()); if (providers == null) { - providers = new LinkedList<>(); - List policyModels = realm.getComponents(realm.getId(), ClientPolicyProvider.class.getName()); - for (ComponentModel policyModel : policyModels) { - try { - ClientPolicyProvider policy = session.getProvider(ClientPolicyProvider.class, policyModel); - ClientPolicyLogger.logv(logger, "Loaded Policy Name = {0}", policyModel.getName()); - session.enlistForClose(policy); - providers.add(policy); - } catch (Throwable t) { - logger.errorv(t, "Failed to load provider {0}", policyModel.getId()); - } - } + providers = realm.getComponentsStream(realm.getId(), ClientPolicyProvider.class.getName()) + .map(policyModel -> { + try { + ClientPolicyProvider policy = session.getProvider(ClientPolicyProvider.class, policyModel); + ClientPolicyLogger.logv(logger, "Loaded Policy Name = {0}", policyModel.getName()); + session.enlistForClose(policy); + return policy; + } catch (Throwable t) { + logger.errorv(t, "Failed to load provider {0}", policyModel.getId()); + return null; + } + }) + .filter(Objects::nonNull) + .collect(Collectors.toList()); providersMap.put(realm.getId(), providers); } else { ClientPolicyLogger.log(logger, "Use cached policies."); diff --git a/services/src/main/java/org/keycloak/services/clientregistration/policy/ClientRegistrationPolicyException.java b/services/src/main/java/org/keycloak/services/clientregistration/policy/ClientRegistrationPolicyException.java index 1ee7a87bd9..20b9afc6f6 100644 --- a/services/src/main/java/org/keycloak/services/clientregistration/policy/ClientRegistrationPolicyException.java +++ b/services/src/main/java/org/keycloak/services/clientregistration/policy/ClientRegistrationPolicyException.java @@ -22,7 +22,7 @@ import org.keycloak.component.ComponentModel; /** * @author Marek Posolda */ -public class ClientRegistrationPolicyException extends Exception { +public class ClientRegistrationPolicyException extends RuntimeException { private ComponentModel policyModel; diff --git a/services/src/main/java/org/keycloak/services/clientregistration/policy/ClientRegistrationPolicyManager.java b/services/src/main/java/org/keycloak/services/clientregistration/policy/ClientRegistrationPolicyManager.java index 23e540aa52..7090011b9a 100644 --- a/services/src/main/java/org/keycloak/services/clientregistration/policy/ClientRegistrationPolicyManager.java +++ b/services/src/main/java/org/keycloak/services/clientregistration/policy/ClientRegistrationPolicyManager.java @@ -17,9 +17,7 @@ package org.keycloak.services.clientregistration.policy; -import java.util.List; -import java.util.function.Consumer; -import java.util.stream.Collectors; +import java.util.Objects; import org.jboss.logging.Logger; import org.keycloak.component.ComponentModel; @@ -97,36 +95,34 @@ public class ClientRegistrationPolicyManager { - private static void triggerPolicies(KeycloakSession session, ClientRegistrationProvider provider, RegistrationAuth authType, String opDescription, ClientRegOperation op) throws ClientRegistrationPolicyException { + private static void triggerPolicies(KeycloakSession session, ClientRegistrationProvider provider, RegistrationAuth authType, + String opDescription, ClientRegOperation op) throws ClientRegistrationPolicyException { RealmModel realm = session.getContext().getRealm(); String policyTypeKey = getComponentTypeKey(authType); - List policyModels = realm.getComponents(realm.getId(), ClientRegistrationPolicy.class.getName()); + realm.getComponentsStream(realm.getId(), ClientRegistrationPolicy.class.getName()) + .filter(componentModel -> Objects.equals(componentModel.getSubType(), policyTypeKey)) + .forEach(policyModel -> runPolicy(policyModel, session, provider, opDescription, op)); + } - policyModels = policyModels.stream().filter((ComponentModel model) -> { + private static void runPolicy(ComponentModel policyModel, KeycloakSession session, ClientRegistrationProvider provider, + String opDescription, ClientRegOperation op) throws ClientRegistrationPolicyException { + ClientRegistrationPolicy policy = session.getProvider(ClientRegistrationPolicy.class, policyModel); + if (policy == null) { + throw new ClientRegistrationPolicyException("Policy of type '" + policyModel.getProviderId() + "' not found"); + } - return policyTypeKey.equals(model.getSubType()); + if (logger.isTraceEnabled()) { + logger.tracef("Running policy '%s' %s", policyModel.getName(), opDescription); + } - }).collect(Collectors.toList()); - - for (ComponentModel policyModel : policyModels) { - ClientRegistrationPolicy policy = session.getProvider(ClientRegistrationPolicy.class, policyModel); - if (policy == null) { - throw new ClientRegistrationPolicyException("Policy of type '" + policyModel.getProviderId() + "' not found"); - } - - if (logger.isTraceEnabled()) { - logger.tracef("Running policy '%s' %s", policyModel.getName(), opDescription); - } - - try { - op.run(policy); - } catch (ClientRegistrationPolicyException crpe) { - provider.getEvent().detail(Details.CLIENT_REGISTRATION_POLICY, policyModel.getName()); - crpe.setPolicyModel(policyModel); - ServicesLogger.LOGGER.clientRegistrationRequestRejected(opDescription, crpe.getMessage()); - throw crpe; - } + try { + op.run(policy); + } catch (ClientRegistrationPolicyException crpe) { + provider.getEvent().detail(Details.CLIENT_REGISTRATION_POLICY, policyModel.getName()); + crpe.setPolicyModel(policyModel); + ServicesLogger.LOGGER.clientRegistrationRequestRejected(opDescription, crpe.getMessage()); + throw crpe; } } diff --git a/services/src/main/java/org/keycloak/services/clientregistration/policy/DefaultClientRegistrationPolicies.java b/services/src/main/java/org/keycloak/services/clientregistration/policy/DefaultClientRegistrationPolicies.java index 54d2be668e..6ef2c8d3fd 100644 --- a/services/src/main/java/org/keycloak/services/clientregistration/policy/DefaultClientRegistrationPolicies.java +++ b/services/src/main/java/org/keycloak/services/clientregistration/policy/DefaultClientRegistrationPolicies.java @@ -19,7 +19,6 @@ package org.keycloak.services.clientregistration.policy; import java.util.Arrays; import java.util.Collections; -import java.util.List; import org.keycloak.component.ComponentModel; import org.keycloak.models.RealmModel; @@ -57,10 +56,9 @@ public class DefaultClientRegistrationPolicies { public static void addDefaultPolicies(RealmModel realm) { String anonPolicyType = ClientRegistrationPolicyManager.getComponentTypeKey(RegistrationAuth.ANONYMOUS); String authPolicyType = ClientRegistrationPolicyManager.getComponentTypeKey(RegistrationAuth.AUTHENTICATED); - List policies = realm.getComponents(realm.getId(), ClientRegistrationPolicy.class.getName()); // Probably an issue if admin removes all policies intentionally... - if (policies == null ||policies.isEmpty()) { + if (realm.getComponentsStream(realm.getId(), ClientRegistrationPolicy.class.getName()).count() == 0) { addAnonymousPolicies(realm, anonPolicyType); addAuthPolicies(realm, authPolicyType); } diff --git a/services/src/main/java/org/keycloak/services/clientregistration/policy/impl/ClientScopesClientRegistrationPolicy.java b/services/src/main/java/org/keycloak/services/clientregistration/policy/impl/ClientScopesClientRegistrationPolicy.java index aed07315f6..a0fe5a6641 100644 --- a/services/src/main/java/org/keycloak/services/clientregistration/policy/impl/ClientScopesClientRegistrationPolicy.java +++ b/services/src/main/java/org/keycloak/services/clientregistration/policy/impl/ClientScopesClientRegistrationPolicy.java @@ -124,13 +124,7 @@ public class ClientScopesClientRegistrationPolicy implements ClientRegistrationP // If allowDefaultScopes, then realm default scopes are allowed as default scopes (+ optional scopes are allowed as optional scopes) boolean allowDefaultScopes = componentModel.get(ClientScopesClientRegistrationPolicyFactory.ALLOW_DEFAULT_SCOPES, true); if (allowDefaultScopes) { - List scopeNames = realm.getDefaultClientScopes(defaultScopes).stream().map((ClientScopeModel clientScope) -> { - - return clientScope.getName(); - - }).collect(Collectors.toList()); - - allAllowed.addAll(scopeNames); + allAllowed.addAll(realm.getDefaultClientScopesStream(defaultScopes).map(ClientScopeModel::getName).collect(Collectors.toList())); } return allAllowed; diff --git a/services/src/main/java/org/keycloak/services/clientregistration/policy/impl/ClientScopesClientRegistrationPolicyFactory.java b/services/src/main/java/org/keycloak/services/clientregistration/policy/impl/ClientScopesClientRegistrationPolicyFactory.java index d32b7fd1b7..96bb5acfdf 100644 --- a/services/src/main/java/org/keycloak/services/clientregistration/policy/impl/ClientScopesClientRegistrationPolicyFactory.java +++ b/services/src/main/java/org/keycloak/services/clientregistration/policy/impl/ClientScopesClientRegistrationPolicyFactory.java @@ -87,13 +87,7 @@ public class ClientScopesClientRegistrationPolicyFactory extends AbstractClientR if (realm == null) { return Collections.emptyList(); } else { - List clientScopes = realm.getClientScopes(); - - return clientScopes.stream().map((ClientScopeModel clientScope) -> { - - return clientScope.getName(); - - }).collect(Collectors.toList()); + return realm.getClientScopesStream().map(ClientScopeModel::getName).collect(Collectors.toList()); } } diff --git a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java index 241ba06616..cec3eac4e1 100755 --- a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java +++ b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java @@ -884,7 +884,7 @@ public class AuthenticationManager { public static Response nextActionAfterAuthentication(KeycloakSession session, AuthenticationSessionModel authSession, ClientConnection clientConnection, HttpRequest request, UriInfo uriInfo, EventBuilder event) { - Response requiredAction = actionRequired(session, authSession, clientConnection, request, uriInfo, event); + Response requiredAction = actionRequired(session, authSession, request, event); if (requiredAction != null) return requiredAction; return finishedRequiredActions(session, authSession, null, clientConnection, request, uriInfo, event); @@ -962,13 +962,12 @@ public class AuthenticationManager { // Return null if action is not required. Or the name of the requiredAction in case it is required. public static String nextRequiredAction(final KeycloakSession session, final AuthenticationSessionModel authSession, - final ClientConnection clientConnection, - final HttpRequest request, final UriInfo uriInfo, final EventBuilder event) { + final HttpRequest request, final EventBuilder event) { final RealmModel realm = authSession.getRealm(); final UserModel user = authSession.getAuthenticatedUser(); final ClientModel client = authSession.getClient(); - evaluateRequiredActionTriggers(session, authSession, clientConnection, request, uriInfo, event, realm, user); + evaluateRequiredActionTriggers(session, authSession, request, event, realm, user); if (!user.getRequiredActions().isEmpty()) { return user.getRequiredActions().iterator().next(); @@ -1018,14 +1017,12 @@ public class AuthenticationManager { public static Response actionRequired(final KeycloakSession session, final AuthenticationSessionModel authSession, - final ClientConnection clientConnection, - final HttpRequest request, final UriInfo uriInfo, final EventBuilder event) { + final HttpRequest request, final EventBuilder event) { final RealmModel realm = authSession.getRealm(); final UserModel user = authSession.getAuthenticatedUser(); final ClientModel client = authSession.getClient(); - evaluateRequiredActionTriggers(session, authSession, clientConnection, request, uriInfo, event, realm, user); - + evaluateRequiredActionTriggers(session, authSession, request, event, realm, user); logger.debugv("processAccessCode: go to oauth page?: {0}", client.isConsentRequired()); @@ -1142,10 +1139,11 @@ public class AuthenticationManager { String kcAction = authSession.getClientNote(Constants.KC_ACTION); if (kcAction != null) { - for (RequiredActionProviderModel m : realm.getRequiredActionProviders()) { - if (m.getProviderId().equals(kcAction)) { - return executeAction(session, authSession, m, request, event, realm, user, true); - } + Optional requiredAction = realm.getRequiredActionProvidersStream() + .filter(m -> Objects.equals(m.getProviderId(), kcAction)) + .findFirst(); + if (requiredAction.isPresent()) { + return executeAction(session, authSession, requiredAction.get(), request, event, realm, user, true); } logger.debugv("Requested action {0} not configured for realm", kcAction); @@ -1230,40 +1228,53 @@ public class AuthenticationManager { return actions; } - public static void evaluateRequiredActionTriggers(final KeycloakSession session, final AuthenticationSessionModel authSession, final ClientConnection clientConnection, final HttpRequest request, final UriInfo uriInfo, final EventBuilder event, final RealmModel realm, final UserModel user) { - + public static void evaluateRequiredActionTriggers(final KeycloakSession session, final AuthenticationSessionModel authSession, + final HttpRequest request, final EventBuilder event, + final RealmModel realm, final UserModel user) { // see if any required actions need triggering, i.e. an expired password - for (RequiredActionProviderModel model : realm.getRequiredActionProviders()) { - if (!model.isEnabled()) continue; - RequiredActionFactory factory = (RequiredActionFactory)session.getKeycloakSessionFactory().getProviderFactory(RequiredActionProvider.class, model.getProviderId()); - if (factory == null) { - throw new RuntimeException("Unable to find factory for Required Action: " + model.getProviderId() + " did you forget to declare it in a META-INF/services file?"); + realm.getRequiredActionProvidersStream() + .filter(RequiredActionProviderModel::isEnabled) + .map(model -> toRequiredActionFactory(session, model)) + .forEachOrdered(f -> evaluateRequiredAction(session, authSession, request, event, realm, user, f)); + } + + private static void evaluateRequiredAction(final KeycloakSession session, final AuthenticationSessionModel authSession, + final HttpRequest request, final EventBuilder event, final RealmModel realm, + final UserModel user, RequiredActionFactory factory) { + RequiredActionProvider provider = factory.create(session); + RequiredActionContextResult result = new RequiredActionContextResult(authSession, realm, event, session, request, user, factory) { + @Override + public void challenge(Response response) { + throw new RuntimeException("Not allowed to call challenge() within evaluateTriggers()"); } - RequiredActionProvider provider = factory.create(session); - RequiredActionContextResult result = new RequiredActionContextResult(authSession, realm, event, session, request, user, factory) { - @Override - public void challenge(Response response) { - throw new RuntimeException("Not allowed to call challenge() within evaluateTriggers()"); - } - @Override - public void failure() { - throw new RuntimeException("Not allowed to call failure() within evaluateTriggers()"); - } + @Override + public void failure() { + throw new RuntimeException("Not allowed to call failure() within evaluateTriggers()"); + } - @Override - public void success() { - throw new RuntimeException("Not allowed to call success() within evaluateTriggers()"); - } + @Override + public void success() { + throw new RuntimeException("Not allowed to call success() within evaluateTriggers()"); + } - @Override - public void ignore() { - throw new RuntimeException("Not allowed to call ignore() within evaluateTriggers()"); - } - }; + @Override + public void ignore() { + throw new RuntimeException("Not allowed to call ignore() within evaluateTriggers()"); + } + }; - provider.evaluateTriggers(result); + provider.evaluateTriggers(result); + } + + private static RequiredActionFactory toRequiredActionFactory(KeycloakSession session, RequiredActionProviderModel model) { + RequiredActionFactory factory = (RequiredActionFactory) session.getKeycloakSessionFactory() + .getProviderFactory(RequiredActionProvider.class, model.getProviderId()); + if (factory == null) { + throw new RuntimeException("Unable to find factory for Required Action: " + + model.getProviderId() + " did you forget to declare it in a META-INF/services file?"); } + return factory; } public static AuthResult verifyIdentityToken(KeycloakSession session, RealmModel realm, UriInfo uriInfo, ClientConnection connection, boolean checkActive, boolean checkTokenType, diff --git a/services/src/main/java/org/keycloak/services/managers/RealmManager.java b/services/src/main/java/org/keycloak/services/managers/RealmManager.java index 715a881408..1a2a015868 100755 --- a/services/src/main/java/org/keycloak/services/managers/RealmManager.java +++ b/services/src/main/java/org/keycloak/services/managers/RealmManager.java @@ -52,7 +52,6 @@ import org.keycloak.representations.idm.RealmEventsConfigRepresentation; import org.keycloak.representations.idm.RealmRepresentation; import org.keycloak.representations.idm.RoleRepresentation; import org.keycloak.sessions.AuthenticationSessionProvider; -import org.keycloak.storage.UserStorageProviderModel; import org.keycloak.services.clientregistration.policy.DefaultClientRegistrationPolicies; import java.util.Collections; @@ -126,11 +125,11 @@ public class RealmManager { } protected void setupAuthenticationFlows(RealmModel realm) { - if (realm.getAuthenticationFlows().size() == 0) DefaultAuthenticationFlows.addFlows(realm); + if (realm.getAuthenticationFlowsStream().count() == 0) DefaultAuthenticationFlows.addFlows(realm); } protected void setupRequiredActions(RealmModel realm) { - if (realm.getRequiredActionProviders().size() == 0) DefaultRequiredActions.addActions(realm); + if (realm.getRequiredActionProvidersStream().count() == 0) DefaultRequiredActions.addActions(realm); } private void setupOfflineTokens(RealmModel realm, RealmRepresentation realmRep) { @@ -270,11 +269,9 @@ public class RealmManager { } // Refresh periodic sync tasks for configured storageProviders - List storageProviders = realm.getUserStorageProviders(); UserStorageSyncManager storageSync = new UserStorageSyncManager(); - for (UserStorageProviderModel provider : storageProviders) { - storageSync.notifyToRefreshPeriodicSync(session, realm, provider, true); - } + realm.getUserStorageProvidersStream() + .forEachOrdered(provider -> storageSync.notifyToRefreshPeriodicSync(session, realm, provider, true)); } return removed; @@ -576,11 +573,9 @@ public class RealmManager { setupRequiredActions(realm); // Refresh periodic sync tasks for configured storageProviders - List storageProviders = realm.getUserStorageProviders(); UserStorageSyncManager storageSync = new UserStorageSyncManager(); - for (UserStorageProviderModel provider : storageProviders) { - storageSync.notifyToRefreshPeriodicSync(session, realm, provider, false); - } + realm.getUserStorageProvidersStream() + .forEachOrdered(provider -> storageSync.notifyToRefreshPeriodicSync(session, realm, provider, false)); setupAuthorizationServices(realm); setupClientRegistrations(realm); diff --git a/services/src/main/java/org/keycloak/services/managers/UserStorageSyncManager.java b/services/src/main/java/org/keycloak/services/managers/UserStorageSyncManager.java index 5c4110fa3a..e6ff2c1f8d 100755 --- a/services/src/main/java/org/keycloak/services/managers/UserStorageSyncManager.java +++ b/services/src/main/java/org/keycloak/services/managers/UserStorageSyncManager.java @@ -35,8 +35,9 @@ import org.keycloak.storage.user.ImportSynchronization; import org.keycloak.storage.user.SynchronizationResult; import org.keycloak.timer.TimerProvider; -import java.util.List; +import java.util.Objects; import java.util.concurrent.Callable; +import java.util.stream.Stream; /** * @author Marek Posolda @@ -58,16 +59,16 @@ public class UserStorageSyncManager { @Override public void run(KeycloakSession session) { - List realms = session.realms().getRealmsWithProviderType(UserStorageProvider.class); - for (final RealmModel realm : realms) { - List providers = realm.getUserStorageProviders(); - for (final UserStorageProviderModel provider : providers) { + Stream realms = session.realms().getRealmsWithProviderTypeStream(UserStorageProvider.class); + realms.forEach(realm -> { + Stream providers = realm.getUserStorageProvidersStream(); + providers.forEachOrdered(provider -> { UserStorageProviderFactory factory = (UserStorageProviderFactory) session.getKeycloakSessionFactory().getProviderFactory(UserStorageProvider.class, provider.getProviderId()); if (factory instanceof ImportSynchronization && provider.isImportEnabled()) { refreshPeriodicSyncForProvider(sessionFactory, timer, provider, realm.getId()); } - } - } + }); + }); ClusterProvider clusterProvider = session.getProvider(ClusterProvider.class); clusterProvider.registerListener(USER_STORAGE_TASK_KEY, new UserStorageClusterListener(sessionFactory)); @@ -254,20 +255,18 @@ public class UserStorageSyncManager { @Override public void run(KeycloakSession session) { RealmModel persistentRealm = session.realms().getRealm(realmId); - List persistentFedProviders = persistentRealm.getUserStorageProviders(); - for (UserStorageProviderModel persistentFedProvider : persistentFedProviders) { - if (provider.getId().equals(persistentFedProvider.getId())) { - // Update persistent provider in DB - int lastSync = Time.currentTime(); - persistentFedProvider.setLastSync(lastSync); - persistentRealm.updateComponent(persistentFedProvider); + persistentRealm.getUserStorageProvidersStream() + .filter(persistentFedProvider -> Objects.equals(provider.getId(), persistentFedProvider.getId())) + .forEachOrdered(persistentFedProvider -> { + // Update persistent provider in DB + int lastSync = Time.currentTime(); + persistentFedProvider.setLastSync(lastSync); + persistentRealm.updateComponent(persistentFedProvider); - // Update "cached" reference - provider.setLastSync(lastSync); - } - } + // Update "cached" reference + provider.setLastSync(lastSync); + }); } - }); } diff --git a/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java b/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java index 6440e01733..0568cd3dcd 100755 --- a/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java +++ b/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java @@ -51,7 +51,6 @@ import org.keycloak.models.ClientModel; import org.keycloak.models.ClientSessionContext; import org.keycloak.models.Constants; import org.keycloak.models.FederatedIdentityModel; -import org.keycloak.models.IdentityProviderMapperModel; import org.keycloak.models.IdentityProviderModel; import org.keycloak.models.IdentityProviderSyncMode; import org.keycloak.models.KeycloakSession; @@ -538,14 +537,12 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal session.getContext().setClient(authenticationSession.getClient()); context.getIdp().preprocessFederatedIdentity(session, realmModel, context); - Set mappers = realmModel.getIdentityProviderMappersByAlias(context.getIdpConfig().getAlias()); - if (mappers != null) { - KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory(); - for (IdentityProviderMapperModel mapper : mappers) { - IdentityProviderMapper target = (IdentityProviderMapper)sessionFactory.getProviderFactory(IdentityProviderMapper.class, mapper.getIdentityProviderMapper()); - target.preprocessFederatedIdentity(session, realmModel, mapper, context); - } - } + KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory(); + realmModel.getIdentityProviderMappersByAliasStream(context.getIdpConfig().getAlias()).forEach(mapper -> { + IdentityProviderMapper target = (IdentityProviderMapper) sessionFactory + .getProviderFactory(IdentityProviderMapper.class, mapper.getIdentityProviderMapper()); + target.preprocessFederatedIdentity(session, realmModel, mapper, context); + }); FederatedIdentityModel federatedIdentityModel = new FederatedIdentityModel(providerId, context.getId(), context.getUsername(), context.getToken()); @@ -717,14 +714,12 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal logger.debugf("Registered new user '%s' after first login with identity provider '%s'. Identity provider username is '%s' . ", federatedUser.getUsername(), providerId, context.getUsername()); context.getIdp().importNewUser(session, realmModel, federatedUser, context); - Set mappers = realmModel.getIdentityProviderMappersByAlias(providerId); - if (mappers != null) { - KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory(); - for (IdentityProviderMapperModel mapper : mappers) { - IdentityProviderMapper target = (IdentityProviderMapper)sessionFactory.getProviderFactory(IdentityProviderMapper.class, mapper.getIdentityProviderMapper()); - target.importNewUser(session, realmModel, federatedUser, mapper, context); - } - } + KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory(); + realmModel.getIdentityProviderMappersByAliasStream(providerId).forEach(mapper -> { + IdentityProviderMapper target = (IdentityProviderMapper) sessionFactory + .getProviderFactory(IdentityProviderMapper.class, mapper.getIdentityProviderMapper()); + target.importNewUser(session, realmModel, federatedUser, mapper, context); + }); if (context.getIdpConfig().isTrustEmail() && !Validation.isBlank(federatedUser.getEmail()) && !Boolean.parseBoolean(authSession.getAuthNote(AbstractIdpAuthenticator.UPDATE_PROFILE_EMAIL_CHANGED))) { logger.debugf("Email verified automatically after registration of user '%s' through Identity provider '%s' ", federatedUser.getUsername(), context.getIdpConfig().getAlias()); @@ -861,7 +856,7 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal AuthenticationManager.setClientScopesInSession(authSession); - String nextRequiredAction = AuthenticationManager.nextRequiredAction(session, authSession, clientConnection, request, session.getContext().getUri(), event); + String nextRequiredAction = AuthenticationManager.nextRequiredAction(session, authSession, request, event); if (nextRequiredAction != null) { if ("true".equals(authSession.getAuthNote(AuthenticationProcessor.FORWARDED_PASSIVE_LOGIN))) { logger.errorf("Required action %s found. Auth requests using prompt=none are incompatible with required actions", nextRequiredAction); @@ -1019,15 +1014,12 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal // Skip DB write if tokens are null or equal updateToken(context, federatedUser, federatedIdentityModel); context.getIdp().updateBrokeredUser(session, realmModel, federatedUser, context); - Set mappers = realmModel.getIdentityProviderMappersByAlias(context.getIdpConfig().getAlias()); - if (mappers != null) { - KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory(); - for (IdentityProviderMapperModel mapper : mappers) { - IdentityProviderMapper target = (IdentityProviderMapper)sessionFactory.getProviderFactory(IdentityProviderMapper.class, mapper.getIdentityProviderMapper()); - IdentityProviderMapperSyncModeDelegate.delegateUpdateBrokeredUser(session, realmModel, federatedUser, mapper, context, target); - } - } - + KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory(); + realmModel.getIdentityProviderMappersByAliasStream(context.getIdpConfig().getAlias()).forEach(mapper -> { + IdentityProviderMapper target = (IdentityProviderMapper) sessionFactory + .getProviderFactory(IdentityProviderMapper.class, mapper.getIdentityProviderMapper()); + IdentityProviderMapperSyncModeDelegate.delegateUpdateBrokeredUser(session, realmModel, federatedUser, mapper, context, target); + }); } private void setBasicUserAttributes(BrokeredIdentityContext context, UserModel federatedUser) { diff --git a/services/src/main/java/org/keycloak/services/resources/account/AccountConsole.java b/services/src/main/java/org/keycloak/services/resources/account/AccountConsole.java index ef152ad6d9..69d12152af 100644 --- a/services/src/main/java/org/keycloak/services/resources/account/AccountConsole.java +++ b/services/src/main/java/org/keycloak/services/resources/account/AccountConsole.java @@ -40,6 +40,7 @@ import java.util.Scanner; import java.util.function.Function; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.stream.Collectors; import javax.ws.rs.core.UriInfo; import org.keycloak.services.resources.RealmsResource; @@ -135,13 +136,9 @@ public class AccountConsole { } } - private Map supportedLocales(Properties messages) throws IOException { - Map supportedLocales = new HashMap<>(); - for (String l : realm.getSupportedLocales()) { - String label = messages.getProperty("locale_" + l, l); - supportedLocales.put(l, label); - } - return supportedLocales; + private Map supportedLocales(Properties messages) { + return realm.getSupportedLocalesStream() + .collect(Collectors.toMap(Function.identity(), l -> messages.getProperty("locale_" + l, l))); } private String messagesToJsonString(Properties props) { diff --git a/services/src/main/java/org/keycloak/services/resources/account/AccountCredentialResource.java b/services/src/main/java/org/keycloak/services/resources/account/AccountCredentialResource.java index 2653185346..0484064ae1 100644 --- a/services/src/main/java/org/keycloak/services/resources/account/AccountCredentialResource.java +++ b/services/src/main/java/org/keycloak/services/resources/account/AccountCredentialResource.java @@ -38,11 +38,13 @@ import javax.ws.rs.core.Response; import java.io.IOException; import java.util.Collections; import java.util.Comparator; -import java.util.HashSet; -import java.util.LinkedList; import java.util.List; +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; import static org.keycloak.models.AuthenticationExecutionModel.Requirement.DISABLED; import static org.keycloak.utils.CredentialHelper.createUserStorageCredentialRepresentation; @@ -147,7 +149,7 @@ public class AccountCredentialResource { /** - * Retrieve the list of credentials available to the current logged in user. It will return only credentials of enabled types, + * Retrieve the stream of credentials available to the current logged in user. It will return only credentials of enabled types, * which user can use to authenticate in some authentication flow. * * @param type Allows to filter just single credential type, which will be specified as this parameter. If null, it will return all credential types @@ -158,14 +160,14 @@ public class AccountCredentialResource { @GET @NoCache @Produces(javax.ws.rs.core.MediaType.APPLICATION_JSON) - public List credentialTypes(@QueryParam(TYPE) String type, + public Stream credentialTypes(@QueryParam(TYPE) String type, @QueryParam(USER_CREDENTIALS) Boolean userCredentials) { auth.requireOneOf(AccountRoles.MANAGE_ACCOUNT, AccountRoles.VIEW_PROFILE); boolean includeUserCredentials = userCredentials == null || userCredentials; - List credentialTypes = new LinkedList<>(); - List credentialProviders = UserCredentialStoreManager.getCredentialProviders(session, realm, CredentialProvider.class); + List credentialProviders = UserCredentialStoreManager.getCredentialProviders(session, CredentialProvider.class) + .collect(Collectors.toList()); Set enabledCredentialTypes = getEnabledCredentialTypes(credentialProviders); List models = includeUserCredentials ? session.userCredentialManager().getStoredCredentials(realm, user) : null; @@ -177,21 +179,7 @@ public class AccountCredentialResource { } } - for (CredentialProvider credentialProvider : credentialProviders) { - String credentialProviderType = credentialProvider.getType(); - - // Filter just by single type - if (type != null && !type.equals(credentialProviderType)) { - continue; - } - - boolean enabled = enabledCredentialTypes.contains(credentialProviderType); - - // Filter disabled credential types - if (!enabled) { - continue; - } - + Function toCredentialContainer = (credentialProvider) -> { CredentialTypeMetadataContext ctx = CredentialTypeMetadataContext.builder() .user(user) .build(session); @@ -205,56 +193,51 @@ public class AccountCredentialResource { .collect(Collectors.toList()); if (userCredentialModels.isEmpty() && - session.userCredentialManager().isConfiguredFor(realm, user, credentialProviderType)) { + session.userCredentialManager().isConfiguredFor(realm, user, credentialProvider.getType())) { // In case user is federated in the userStorage, he may have credential configured on the userStorage side. We're // creating "dummy" credential representing the credential provided by userStorage - CredentialRepresentation credential = createUserStorageCredentialRepresentation(credentialProviderType); - + CredentialRepresentation credential = createUserStorageCredentialRepresentation(credentialProvider.getType()); userCredentialModels = Collections.singletonList(credential); } // In case that there are no userCredentials AND there are not required actions for setup new credential, // we won't include credentialType as user won't be able to do anything with it if (userCredentialModels.isEmpty() && metadata.getCreateAction() == null && metadata.getUpdateAction() == null) { - continue; + return null; } } - CredentialContainer credType = new CredentialContainer(metadata, userCredentialModels); - credentialTypes.add(credType); - } + return new CredentialContainer(metadata, userCredentialModels); + }; - credentialTypes.sort(Comparator.comparing(CredentialContainer::getMetadata)); - - return credentialTypes; + return credentialProviders.stream() + .filter(p -> type == null || Objects.equals(p.getType(), type)) + .filter(p -> enabledCredentialTypes.contains(p.getType())) + .map(toCredentialContainer) + .filter(Objects::nonNull) + .sorted(Comparator.comparing(CredentialContainer::getMetadata)); } // Going through all authentication flows and their authentication executions to see if there is any authenticator of the corresponding // credential type. private Set getEnabledCredentialTypes(List credentialProviders) { - Set enabledCredentialTypes = new HashSet<>(); - - for (AuthenticationFlowModel flow : realm.getAuthenticationFlows()) { - // Ignore DISABLED executions and flows - if (isFlowEffectivelyDisabled(flow)) continue; - - for (AuthenticationExecutionModel execution : realm.getAuthenticationExecutions(flow.getId())) { - if (execution.getAuthenticator() != null && DISABLED != execution.getRequirement()) { - AuthenticatorFactory authenticatorFactory = (AuthenticatorFactory) session.getKeycloakSessionFactory().getProviderFactory(Authenticator.class, execution.getAuthenticator()); - if (authenticatorFactory != null && authenticatorFactory.getReferenceCategory() != null) { - enabledCredentialTypes.add(authenticatorFactory.getReferenceCategory()); - } - } - } - } + Stream enabledCredentialTypes = realm.getAuthenticationFlowsStream() + .filter(((Predicate) this::isFlowEffectivelyDisabled).negate()) + .flatMap(flow -> + realm.getAuthenticationExecutionsStream(flow.getId()) + .filter(exe -> Objects.nonNull(exe.getAuthenticator()) && exe.getRequirement() != DISABLED) + .map(exe -> (AuthenticatorFactory) session.getKeycloakSessionFactory() + .getProviderFactory(Authenticator.class, exe.getAuthenticator())) + .filter(Objects::nonNull) + .map(AuthenticatorFactory::getReferenceCategory) + .filter(Objects::nonNull) + ); Set credentialTypes = credentialProviders.stream() .map(CredentialProvider::getType) .collect(Collectors.toSet()); - enabledCredentialTypes.retainAll(credentialTypes); - - return enabledCredentialTypes; + return enabledCredentialTypes.filter(credentialTypes::contains).collect(Collectors.toSet()); } // Returns true if flow is effectively disabled - either it's execution or some parent execution is disabled diff --git a/services/src/main/java/org/keycloak/services/resources/account/AccountFormService.java b/services/src/main/java/org/keycloak/services/resources/account/AccountFormService.java index bd9abde011..2860a465f9 100755 --- a/services/src/main/java/org/keycloak/services/resources/account/AccountFormService.java +++ b/services/src/main/java/org/keycloak/services/resources/account/AccountFormService.java @@ -43,7 +43,6 @@ import org.keycloak.models.AccountRoles; import org.keycloak.models.AuthenticatedClientSessionModel; import org.keycloak.models.ClientModel; import org.keycloak.models.FederatedIdentityModel; -import org.keycloak.models.IdentityProviderModel; import org.keycloak.models.KeycloakSession; import org.keycloak.models.ModelException; import org.keycloak.models.OTPPolicy; @@ -109,8 +108,10 @@ import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.UUID; +import java.util.stream.Collectors; /** * @author Stian Thorgersen @@ -298,17 +299,20 @@ public class AccountFormService extends AbstractSecuredLocalService { } if (auth != null) { - List events = eventStore.createQuery().type(Constants.EXPOSED_LOG_EVENTS).realm(auth.getRealm().getId()).user(auth.getUser().getId()).maxResults(30).getResultList(); - for (Event e : events) { - if (e.getDetails() != null) { - Iterator> itr = e.getDetails().entrySet().iterator(); - while (itr.hasNext()) { - if (!Constants.EXPOSED_LOG_DETAILS.contains(itr.next().getKey())) { - itr.remove(); + List events = eventStore.createQuery().type(Constants.EXPOSED_LOG_EVENTS) + .realm(auth.getRealm().getId()).user(auth.getUser().getId()).maxResults(30) + .getResultStream() + .peek(e -> { + if (e.getDetails() != null) { + Iterator> itr = e.getDetails().entrySet().iterator(); + while (itr.hasNext()) { + if (!Constants.EXPOSED_LOG_DETAILS.contains(itr.next().getKey())) { + itr.remove(); + } + } } - } - } - } + }) + .collect(Collectors.toList()); account.setEvents(events); } return forwardToPage("log", AccountPages.LOG); @@ -665,15 +669,7 @@ public class AccountFormService extends AbstractSecuredLocalService { return account.setError(Status.OK, Messages.INVALID_FEDERATED_IDENTITY_ACTION).createResponse(AccountPages.FEDERATED_IDENTITY); } - boolean hasProvider = false; - - for (IdentityProviderModel model : realm.getIdentityProviders()) { - if (model.getAlias().equals(providerId)) { - hasProvider = true; - } - } - - if (!hasProvider) { + if (!realm.getIdentityProvidersStream().anyMatch(model -> Objects.equals(model.getAlias(), providerId))) { setReferrerOnPage(); return account.setError(Status.OK, Messages.IDENTITY_PROVIDER_NOT_FOUND).createResponse(AccountPages.FEDERATED_IDENTITY); } diff --git a/services/src/main/java/org/keycloak/services/resources/account/AccountRestService.java b/services/src/main/java/org/keycloak/services/resources/account/AccountRestService.java index c728f30873..265982da04 100755 --- a/services/src/main/java/org/keycloak/services/resources/account/AccountRestService.java +++ b/services/src/main/java/org/keycloak/services/resources/account/AccountRestService.java @@ -77,6 +77,7 @@ import java.util.Locale; import java.util.Map; import java.util.Properties; import java.util.Set; +import java.util.function.Function; import java.util.stream.Collectors; /** @@ -373,7 +374,8 @@ public class AccountRestService { */ private UserConsentModel createConsent(ClientModel client, ConsentRepresentation requested) throws IllegalArgumentException { UserConsentModel consent = new UserConsentModel(client); - Map availableGrants = realm.getClientScopes().stream().collect(Collectors.toMap(ClientScopeModel::getId, s -> s)); + Map availableGrants = realm.getClientScopesStream() + .collect(Collectors.toMap(ClientScopeModel::getId, Function.identity())); if (client.isConsentRequired()) { availableGrants.put(client.getId(), client); diff --git a/services/src/main/java/org/keycloak/services/resources/account/LinkedAccountsResource.java b/services/src/main/java/org/keycloak/services/resources/account/LinkedAccountsResource.java index 6d9e3dcbea..c3d48a337d 100644 --- a/services/src/main/java/org/keycloak/services/resources/account/LinkedAccountsResource.java +++ b/services/src/main/java/org/keycloak/services/resources/account/LinkedAccountsResource.java @@ -19,12 +19,8 @@ package org.keycloak.services.resources.account; import java.net.URI; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.SortedSet; -import java.util.TreeSet; -import java.util.UUID; +import java.util.*; +import java.util.stream.Collectors; import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.Path; @@ -38,7 +34,6 @@ import org.jboss.logging.Logger; import org.jboss.resteasy.spi.HttpRequest; import org.keycloak.broker.social.SocialIdentityProvider; import org.keycloak.common.util.Base64Url; -import org.keycloak.credential.CredentialModel; import org.keycloak.events.Details; import org.keycloak.events.EventBuilder; import org.keycloak.events.EventType; @@ -114,38 +109,33 @@ public class LinkedAccountsResource { } public SortedSet getLinkedAccounts(KeycloakSession session, RealmModel realm, UserModel user) { - List identityProviders = realm.getIdentityProviders(); - SortedSet linkedAccounts = new TreeSet<>(); - - if (identityProviders == null || identityProviders.isEmpty()) return linkedAccounts; - Set socialIds = findSocialIds(); Set identities = session.users().getFederatedIdentities(user, realm); - for (IdentityProviderModel provider : identityProviders) { - if (!provider.isEnabled()) { - continue; - } - String providerId = provider.getAlias(); + return realm.getIdentityProvidersStream().filter(IdentityProviderModel::isEnabled) + .map(provider -> toLinkedAccountRepresentation(provider, socialIds, identities)) + .collect(Collectors.toCollection(TreeSet::new)); + } - FederatedIdentityModel identity = getIdentity(identities, providerId); + private LinkedAccountRepresentation toLinkedAccountRepresentation(IdentityProviderModel provider, Set socialIds, + Set identities) { + String providerId = provider.getAlias(); - String displayName = KeycloakModelUtils.getIdentityProviderDisplayName(session, provider); - String guiOrder = provider.getConfig() != null ? provider.getConfig().get("guiOrder") : null; + FederatedIdentityModel identity = getIdentity(identities, providerId); - LinkedAccountRepresentation rep = new LinkedAccountRepresentation(); - rep.setConnected(identity != null); - rep.setSocial(socialIds.contains(provider.getProviderId())); - rep.setProviderAlias(providerId); - rep.setDisplayName(displayName); - rep.setGuiOrder(guiOrder); - rep.setProviderName(provider.getAlias()); - if (identity != null) { - rep.setLinkedUsername(identity.getUserName()); - } - linkedAccounts.add(rep); + String displayName = KeycloakModelUtils.getIdentityProviderDisplayName(session, provider); + String guiOrder = provider.getConfig() != null ? provider.getConfig().get("guiOrder") : null; + + LinkedAccountRepresentation rep = new LinkedAccountRepresentation(); + rep.setConnected(identity != null); + rep.setSocial(socialIds.contains(provider.getProviderId())); + rep.setProviderAlias(providerId); + rep.setDisplayName(displayName); + rep.setGuiOrder(guiOrder); + rep.setProviderName(provider.getAlias()); + if (identity != null) { + rep.setLinkedUsername(identity.getUserName()); } - - return linkedAccounts; + return rep; } private FederatedIdentityModel getIdentity(Set identities, String providerId) { @@ -259,12 +249,6 @@ public class LinkedAccountsResource { } private boolean isValidProvider(String providerId) { - for (IdentityProviderModel model : realm.getIdentityProviders()) { - if (model.getAlias().equals(providerId)) { - return true; - } - } - - return false; + return realm.getIdentityProvidersStream().anyMatch(model -> Objects.equals(model.getAlias(), providerId)); } } diff --git a/services/src/main/java/org/keycloak/services/resources/admin/AdminConsole.java b/services/src/main/java/org/keycloak/services/resources/admin/AdminConsole.java index 824af75483..51d02014a6 100644 --- a/services/src/main/java/org/keycloak/services/resources/admin/AdminConsole.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/AdminConsole.java @@ -59,7 +59,6 @@ import java.net.URI; import java.net.URISyntaxException; import java.util.HashMap; import java.util.HashSet; -import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Properties; @@ -240,11 +239,10 @@ public class AdminConsole { } private void addMasterRealmAccess(UserModel user, Map> realmAdminAccess) { - List realms = session.realms().getRealms(); - for (RealmModel realm : realms) { + session.realms().getRealmsStream().forEach(realm -> { ClientModel realmAdminApp = realm.getMasterAdminClient(); getRealmAdminAccess(realm, realmAdminApp, user, realmAdminAccess); - } + }); } diff --git a/services/src/main/java/org/keycloak/services/resources/admin/AdminEventBuilder.java b/services/src/main/java/org/keycloak/services/resources/admin/AdminEventBuilder.java index 305d6f7e55..f497c9ba80 100644 --- a/services/src/main/java/org/keycloak/services/resources/admin/AdminEventBuilder.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/AdminEventBuilder.java @@ -36,7 +36,7 @@ import javax.ws.rs.core.UriInfo; import java.io.IOException; import java.util.HashMap; import java.util.Map; -import java.util.Set; +import java.util.function.Predicate; public class AdminEventBuilder { @@ -94,19 +94,16 @@ public class AdminEventBuilder { } private AdminEventBuilder addListeners(KeycloakSession session) { - Set extraListeners = realm.getEventsListeners(); - if (extraListeners != null && !extraListeners.isEmpty()) { - for (String id : extraListeners) { - if (!listeners.containsKey(id)) { + realm.getEventsListenersStream() + .filter(((Predicate) listeners::containsKey).negate()) + .forEach(id -> { EventListenerProvider listener = session.getProvider(EventListenerProvider.class, id); if (listener != null) { listeners.put(id, listener); } else { ServicesLogger.LOGGER.providerNotFound(id); } - } - } - } + }); return this; } diff --git a/services/src/main/java/org/keycloak/services/resources/admin/AuthenticationManagementResource.java b/services/src/main/java/org/keycloak/services/resources/admin/AuthenticationManagementResource.java index c4c3145e5b..66df1f69f1 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/AuthenticationManagementResource.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/AuthenticationManagementResource.java @@ -69,7 +69,12 @@ import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Optional; +import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; +import java.util.stream.Stream; import static javax.ws.rs.core.Response.Status.NOT_FOUND; import org.keycloak.utils.ReservedCharValidator; @@ -182,17 +187,12 @@ public class AuthenticationManagementResource { @GET @NoCache @Produces(MediaType.APPLICATION_JSON) - public List getFlows() { + public Stream getFlows() { auth.realm().requireViewAuthenticationFlows(); - List flows = new LinkedList<>(); - for (AuthenticationFlowModel flow : realm.getAuthenticationFlows()) { - // KEYCLOAK-3517, we need a better way to filter non-configurable internal flows - if (flow.isTopLevel() && !flow.getAlias().equals(DefaultAuthenticationFlows.SAML_ECP_FLOW)) { - flows.add(ModelToRepresentation.toRepresentation(realm, flow)); - } - } - return flows; + return realm.getAuthenticationFlowsStream() + .filter(flow -> flow.isTopLevel() && !Objects.equals(flow.getAlias(), DefaultAuthenticationFlows.SAML_ECP_FLOW)) + .map(flow -> ModelToRepresentation.toRepresentation(realm, flow)); } /** @@ -321,12 +321,11 @@ public class AuthenticationManagementResource { throw new BadRequestException("Can't delete built in flow"); } - List executions = realm.getAuthenticationExecutions(id); - for (AuthenticationExecutionModel execution : executions) { - if(execution.getFlowId() != null) { - deleteFlow(execution.getFlowId(), false); - } - } + realm.getAuthenticationExecutionsStream(id) + .map(AuthenticationExecutionModel::getFlowId) + .filter(Objects::nonNull) + .forEachOrdered(flowId -> deleteFlow(flowId, false)); + realm.removeAuthenticationFlow(flow); // Use just one event for top-level flow. Using separate events won't work properly for flows of depth 2 or bigger @@ -380,7 +379,7 @@ public class AuthenticationManagementResource { } public static void copy(RealmModel realm, String newName, AuthenticationFlowModel from, AuthenticationFlowModel to) { - for (AuthenticationExecutionModel execution : realm.getAuthenticationExecutions(from.getId())) { + realm.getAuthenticationExecutionsStream(from.getId()).forEachOrdered(execution -> { if (execution.isAuthenticatorFlow()) { AuthenticationFlowModel subFlow = realm.getAuthenticationFlowById(execution.getFlowId()); AuthenticationFlowModel copy = new AuthenticationFlowModel(); @@ -396,7 +395,7 @@ public class AuthenticationManagementResource { execution.setId(null); execution.setParentFlow(to.getId()); realm.addAuthenticatorExecution(execution); - } + }); } /** @@ -448,7 +447,8 @@ public class AuthenticationManagementResource { } private int getNextPriority(AuthenticationFlowModel parentFlow) { - List executions = getSortedExecutions(parentFlow); + List executions = realm.getAuthenticationExecutionsStream(parentFlow.getId()) + .collect(Collectors.toList()); return executions.isEmpty() ? 0 : executions.get(executions.size() - 1).getPriority() + 1; } @@ -535,13 +535,12 @@ public class AuthenticationManagementResource { } public void recurseExecutions(AuthenticationFlowModel flow, List result, int level) { - int index = 0; - List executions = realm.getAuthenticationExecutions(flow.getId()); - for (AuthenticationExecutionModel execution : executions) { + AtomicInteger index = new AtomicInteger(0); + realm.getAuthenticationExecutionsStream(flow.getId()).forEachOrdered(execution -> { AuthenticationExecutionInfoRepresentation rep = new AuthenticationExecutionInfoRepresentation(); rep.setLevel(level); - rep.setIndex(index++); - rep.setRequirementChoices(new LinkedList()); + rep.setIndex(index.getAndIncrement()); + rep.setRequirementChoices(new LinkedList<>()); if (execution.isAuthenticatorFlow()) { AuthenticationFlowModel flowRef = realm.getAuthenticationFlowById(execution.getFlowId()); if (AuthenticationFlow.BASIC_FLOW.equals(flowRef.getProviderId())) { @@ -595,7 +594,7 @@ public class AuthenticationManagementResource { rep.setAuthenticationConfig(execution.getAuthenticatorConfig()); result.add(rep); } - } + }); } /** @@ -739,9 +738,9 @@ public class AuthenticationManagementResource { if (parentFlow.isBuiltIn()) { throw new BadRequestException("It is illegal to modify execution in a built in flow"); } - List executions = getSortedExecutions(parentFlow); + AuthenticationExecutionModel previous = null; - for (AuthenticationExecutionModel exe : executions) { + for (AuthenticationExecutionModel exe : realm.getAuthenticationExecutionsStream(parentFlow.getId()).collect(Collectors.toList())) { if (exe.getId().equals(model.getId())) { break; } @@ -758,12 +757,6 @@ public class AuthenticationManagementResource { adminEvent.operation(OperationType.UPDATE).resource(ResourceType.AUTH_EXECUTION).resourcePath(session.getContext().getUri()).success(); } - public List getSortedExecutions(AuthenticationFlowModel parentFlow) { - List executions = new LinkedList<>(realm.getAuthenticationExecutions(parentFlow.getId())); - Collections.sort(executions, AuthenticationExecutionModel.ExecutionComparator.SINGLETON); - return executions; - } - /** * Lower execution's priority * @@ -785,8 +778,8 @@ public class AuthenticationManagementResource { if (parentFlow.isBuiltIn()) { throw new BadRequestException("It is illegal to modify execution in a built in flow"); } - List executions = getSortedExecutions(parentFlow); - int i = 0; + List executions = realm.getAuthenticationExecutionsStream(parentFlow.getId()).collect(Collectors.toList()); + int i; for (i = 0; i < executions.size(); i++) { if (executions.get(i).getId().equals(model.getId())) { break; @@ -903,29 +896,22 @@ public class AuthenticationManagementResource { @GET @Produces(MediaType.APPLICATION_JSON) @NoCache - public List> getUnregisteredRequiredActions() { + public Stream> getUnregisteredRequiredActions() { auth.realm().requireViewRealm(); - List factories = session.getKeycloakSessionFactory().getProviderFactories(RequiredActionProvider.class); - List> unregisteredList = new LinkedList<>(); - for (ProviderFactory factory : factories) { - RequiredActionFactory requiredActionFactory = (RequiredActionFactory) factory; - boolean found = false; - for (RequiredActionProviderModel model : realm.getRequiredActionProviders()) { - if (model.getProviderId().equals(factory.getId())) { - found = true; - break; - } - } - if (!found) { - Map data = new HashMap<>(); - data.put("name", requiredActionFactory.getDisplayText()); - data.put("providerId", requiredActionFactory.getId()); - unregisteredList.add(data); - } + Set providerIds = realm.getRequiredActionProvidersStream() + .map(RequiredActionProviderModel::getProviderId).collect(Collectors.toSet()); - } - return unregisteredList; + return session.getKeycloakSessionFactory().getProviderFactories(RequiredActionProvider.class) + .stream() + .filter(factory -> !providerIds.contains(factory.getId())) + .map(factory -> { + RequiredActionFactory r = (RequiredActionFactory) factory; + Map m = new HashMap<>(); + m.put("name", r.getDisplayText()); + m.put("providerId", r.getId()); + return m; + }); } /** @@ -956,7 +942,7 @@ public class AuthenticationManagementResource { } private int getNextRequiredActionPriority() { - List actions = realm.getRequiredActionProviders(); + List actions = realm.getRequiredActionProvidersStream().collect(Collectors.toList()); return actions.isEmpty() ? 0 : actions.get(actions.size() - 1).getPriority() + 1; } @@ -970,15 +956,10 @@ public class AuthenticationManagementResource { @GET @Produces(MediaType.APPLICATION_JSON) @NoCache - public List getRequiredActions() { + public Stream getRequiredActions() { auth.realm().requireViewRequiredActions(); - List list = new LinkedList<>(); - for (RequiredActionProviderModel model : realm.getRequiredActionProviders()) { - RequiredActionProviderRepresentation rep = toRepresentation(model); - list.add(rep); - } - return list; + return realm.getRequiredActionProvidersStream().map(AuthenticationManagementResource::toRepresentation); } public static RequiredActionProviderRepresentation toRepresentation(RequiredActionProviderModel model) { @@ -1076,9 +1057,8 @@ public class AuthenticationManagementResource { throw new NotFoundException("Failed to find required action."); } - List actions = realm.getRequiredActionProviders(); RequiredActionProviderModel previous = null; - for (RequiredActionProviderModel action : actions) { + for (RequiredActionProviderModel action : realm.getRequiredActionProvidersStream().collect(Collectors.toList())) { if (action.getId().equals(model.getId())) { break; } @@ -1110,8 +1090,8 @@ public class AuthenticationManagementResource { throw new NotFoundException("Failed to find required action."); } - List actions = realm.getRequiredActionProviders(); - int i = 0; + List actions = realm.getRequiredActionProvidersStream().collect(Collectors.toList()); + int i; for (i = 0; i < actions.size(); i++) { if (actions.get(i).getId().equals(model.getId())) { break; @@ -1242,14 +1222,12 @@ public class AuthenticationManagementResource { throw new NotFoundException("Could not find authenticator config"); } - for (AuthenticationFlowModel flow : realm.getAuthenticationFlows()) { - for (AuthenticationExecutionModel exe : realm.getAuthenticationExecutions(flow.getId())) { - if (id.equals(exe.getAuthenticatorConfig())) { + realm.getAuthenticationFlowsStream().forEach(flow -> realm.getAuthenticationExecutionsStream(flow.getId()) + .filter(exe -> Objects.equals(id, exe.getAuthenticatorConfig())) + .forEachOrdered(exe -> { exe.setAuthenticatorConfig(null); realm.updateAuthenticatorExecution(exe); - } - } - } + })); realm.removeAuthenticatorConfig(config); diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ClientInitialAccessResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ClientInitialAccessResource.java index 23e67bf626..ee6b38183b 100644 --- a/services/src/main/java/org/keycloak/services/resources/admin/ClientInitialAccessResource.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/ClientInitialAccessResource.java @@ -39,8 +39,7 @@ import javax.ws.rs.core.Context; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; -import java.util.LinkedList; -import java.util.List; +import java.util.stream.Stream; /** * @resource Client Initial Access @@ -94,16 +93,10 @@ public class ClientInitialAccessResource { @GET @Produces(MediaType.APPLICATION_JSON) - public List list() { + public Stream list() { auth.clients().requireView(); - List models = session.realms().listClientInitialAccess(realm); - List reps = new LinkedList<>(); - for (ClientInitialAccessModel m : models) { - ClientInitialAccessPresentation r = wrap(m); - reps.add(r); - } - return reps; + return session.realms().listClientInitialAccessStream(realm).map(this::wrap); } @DELETE diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ClientScopesResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ClientScopesResource.java index 91847f51eb..c23d1d9c96 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/ClientScopesResource.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/ClientScopesResource.java @@ -41,8 +41,7 @@ import javax.ws.rs.Produces; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; -import java.util.ArrayList; -import java.util.List; +import java.util.stream.Stream; /** * Base resource class for managing a realm's client scopes. @@ -74,23 +73,12 @@ public class ClientScopesResource { @GET @Produces(MediaType.APPLICATION_JSON) @NoCache - public List getClientScopes() { + public Stream getClientScopes() { auth.clients().requireListClientScopes(); - List rep = new ArrayList<>(); - List clientModels = realm.getClientScopes(); - - boolean viewable = auth.clients().canViewClientScopes(); - for (ClientScopeModel clientModel : clientModels) { - if (viewable) rep.add(ModelToRepresentation.toRepresentation(clientModel)); - else { - ClientScopeRepresentation tempRep = new ClientScopeRepresentation(); - tempRep.setName(clientModel.getName()); - tempRep.setId(clientModel.getId()); - tempRep.setProtocol(clientModel.getProtocol()); - } - } - return rep; + return auth.clients().canViewClientScopes() ? + realm.getClientScopesStream().map(ModelToRepresentation::toRepresentation) : + Stream.empty(); } /** diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ComponentResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ComponentResource.java index b25ee79071..50a884b263 100644 --- a/services/src/main/java/org/keycloak/services/resources/admin/ComponentResource.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/ComponentResource.java @@ -55,12 +55,8 @@ import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import java.text.MessageFormat; -import java.util.Arrays; -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Properties; +import java.util.*; +import java.util.stream.Stream; /** * @resource Component @@ -94,34 +90,32 @@ public class ComponentResource { @GET @Produces(MediaType.APPLICATION_JSON) @NoCache - public List getComponents(@QueryParam("parent") String parent, + public Stream getComponents(@QueryParam("parent") String parent, @QueryParam("type") String type, @QueryParam("name") String name) { auth.realm().requireViewRealm(); - List components = Collections.EMPTY_LIST; + Stream components; if (parent == null && type == null) { - components = realm.getComponents(); + components = realm.getComponentsStream(); } else if (type == null) { - components = realm.getComponents(parent); + components = realm.getComponentsStream(parent); } else if (parent == null) { - components = realm.getComponents(realm.getId(), type); + components = realm.getComponentsStream(realm.getId(), type); } else { - components = realm.getComponents(parent, type); + components = realm.getComponentsStream(parent, type); } - List reps = new LinkedList<>(); - for (ComponentModel component : components) { - if (name != null && !name.equals(component.getName())) continue; - ComponentRepresentation rep = null; - try { - rep = ModelToRepresentation.toRepresentation(session, component, false); - } catch (Exception e) { - logger.error("Failed to get component list for component model" + component.getName() + "of realm " + realm.getName()); - rep = ModelToRepresentation.toRepresentationWithoutConfig(component); - } - reps.add(rep); - } - return reps; + + return components + .filter(component -> Objects.isNull(name) || Objects.equals(component.getName(), name)) + .map(component -> { + try { + return ModelToRepresentation.toRepresentation(session, component, false); + } catch (Exception e) { + logger.error("Failed to get component list for component model" + component.getName() + "of realm " + realm.getName()); + return ModelToRepresentation.toRepresentationWithoutConfig(component); + } + }); } @POST 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 9aeb0fd19a..efebc5fe15 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 @@ -21,15 +21,12 @@ import static javax.ws.rs.core.Response.Status.BAD_REQUEST; import org.jboss.logging.Logger; import org.jboss.resteasy.annotations.cache.NoCache; import javax.ws.rs.NotFoundException; -import org.keycloak.authorization.model.Resource; -import org.keycloak.authorization.model.ResourceServer; import org.keycloak.broker.provider.IdentityProvider; import org.keycloak.broker.provider.IdentityProviderFactory; import org.keycloak.broker.provider.IdentityProviderMapper; import org.keycloak.broker.social.SocialIdentityProvider; import org.keycloak.events.admin.OperationType; import org.keycloak.events.admin.ResourceType; -import org.keycloak.models.ClientModel; import org.keycloak.models.FederatedIdentityModel; import org.keycloak.models.IdentityProviderMapperModel; import org.keycloak.models.IdentityProviderModel; @@ -63,16 +60,11 @@ import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; -import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; -import javax.ws.rs.core.UriInfo; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; /** * @resource Identity Providers @@ -133,10 +125,8 @@ public class IdentityProviderResource { session.users().preRemove(realm, identityProviderModel); this.realm.removeIdentityProviderByAlias(alias); - Set mappers = this.realm.getIdentityProviderMappersByAlias(alias); - for (IdentityProviderMapperModel mapper : mappers) { - this.realm.removeIdentityProviderMapper(mapper); - } + realm.getIdentityProviderMappersByAliasStream(alias) + .collect(Collectors.toList()).forEach(realm::removeIdentityProviderMapper); adminEvent.operation(OperationType.DELETE).resourcePath(session.getContext().getUri()).success(); @@ -206,26 +196,20 @@ public class IdentityProviderResource { // return ID of IdentityProvider from realm based on internalId of this provider private static String getProviderIdByInternalId(RealmModel realm, String providerInternalId) { - List providerModels = realm.getIdentityProviders(); - for (IdentityProviderModel providerModel : providerModels) { - if (providerModel.getInternalId().equals(providerInternalId)) { - return providerModel.getAlias(); - } - } - - return null; + return realm.getIdentityProvidersStream().filter(p -> Objects.equals(p.getInternalId(), providerInternalId)) + .map(IdentityProviderModel::getAlias) + .findFirst() + .orElse(null); } // sets internalId to IdentityProvider based on alias private static void lookUpProviderIdByAlias(RealmModel realm, IdentityProviderRepresentation providerRep) { - List providerModels = realm.getIdentityProviders(); - for (IdentityProviderModel providerModel : providerModels) { - if (providerModel.getAlias().equals(providerRep.getAlias())) { - providerRep.setInternalId(providerModel.getInternalId()); - return; - } - } - throw new javax.ws.rs.NotFoundException(); + IdentityProviderModel identityProviderModel = realm.getIdentityProvidersStream() + .filter(p -> Objects.equals(p.getAlias(), providerRep.getAlias())) + .findFirst() + .orElseThrow(NotFoundException::new); + + providerRep.setInternalId(identityProviderModel.getInternalId()); } private static void updateUsersAfterProviderAliasChange(List users, String oldProviderId, String newProviderId, RealmModel realm, KeycloakSession session) { @@ -326,18 +310,15 @@ public class IdentityProviderResource { @Path("mappers") @Produces(MediaType.APPLICATION_JSON) @NoCache - public List getMappers() { + public Stream getMappers() { this.auth.realm().requireViewIdentityProviders(); if (identityProviderModel == null) { throw new javax.ws.rs.NotFoundException(); } - List mappers = new LinkedList<>(); - for (IdentityProviderMapperModel model : realm.getIdentityProviderMappersByAlias(identityProviderModel.getAlias())) { - mappers.add(ModelToRepresentation.toRepresentation(model)); - } - return mappers; + return realm.getIdentityProviderMappersByAliasStream(identityProviderModel.getAlias()) + .map(ModelToRepresentation::toRepresentation); } /** diff --git a/services/src/main/java/org/keycloak/services/resources/admin/IdentityProvidersResource.java b/services/src/main/java/org/keycloak/services/resources/admin/IdentityProvidersResource.java index 388672f5a2..788444abee 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/IdentityProvidersResource.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/IdentityProvidersResource.java @@ -53,6 +53,8 @@ import java.io.InputStream; import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.Objects; +import java.util.stream.Stream; import static javax.ws.rs.core.Response.Status.BAD_REQUEST; import org.keycloak.utils.ReservedCharValidator; @@ -163,15 +165,11 @@ public class IdentityProvidersResource { @Path("instances") @NoCache @Produces(MediaType.APPLICATION_JSON) - public List getIdentityProviders() { + public Stream getIdentityProviders() { this.auth.realm().requireViewIdentityProviders(); - List representations = new ArrayList(); - - for (IdentityProviderModel identityProviderModel : realm.getIdentityProviders()) { - representations.add(StripSecretsUtils.strip(ModelToRepresentation.toRepresentation(realm, identityProviderModel))); - } - return representations; + return realm.getIdentityProvidersStream() + .map(provider -> StripSecretsUtils.strip(ModelToRepresentation.toRepresentation(realm, provider))); } /** @@ -213,14 +211,9 @@ public class IdentityProvidersResource { @Path("instances/{alias}") public IdentityProviderResource getIdentityProvider(@PathParam("alias") String alias) { this.auth.realm().requireViewIdentityProviders(); - IdentityProviderModel identityProviderModel = null; - - for (IdentityProviderModel storedIdentityProvider : this.realm.getIdentityProviders()) { - if (storedIdentityProvider.getAlias().equals(alias) - || storedIdentityProvider.getInternalId().equals(alias)) { - identityProviderModel = storedIdentityProvider; - } - } + IdentityProviderModel identityProviderModel = this.realm.getIdentityProvidersStream() + .filter(p -> Objects.equals(p.getAlias(), alias) || Objects.equals(p.getInternalId(), alias)) + .findFirst().orElse(null); IdentityProviderResource identityProviderResource = new IdentityProviderResource(this.auth, realm, session, identityProviderModel, adminEvent); ResteasyProviderFactory.getInstance().injectProperties(identityProviderResource); diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java index b0febd974c..4d18bb4ef4 100644 --- a/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java @@ -22,14 +22,12 @@ import static org.keycloak.util.JsonSerialization.readValue; import java.security.cert.X509Certificate; import java.text.ParseException; import java.text.SimpleDateFormat; -import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; -import java.util.stream.Collectors; import java.util.stream.Stream; import javax.ws.rs.BadRequestException; @@ -61,11 +59,9 @@ import org.keycloak.common.ClientConnection; import org.keycloak.common.VerificationException; import org.keycloak.common.util.PemUtils; import org.keycloak.email.EmailTemplateProvider; -import org.keycloak.events.Event; import org.keycloak.events.EventQuery; import org.keycloak.events.EventStoreProvider; import org.keycloak.events.EventType; -import org.keycloak.events.admin.AdminEvent; import org.keycloak.events.admin.AdminEventQuery; import org.keycloak.events.admin.OperationType; import org.keycloak.events.admin.ResourceType; @@ -116,7 +112,6 @@ import org.keycloak.services.managers.UserStorageSyncManager; import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator; import org.keycloak.services.resources.admin.permissions.AdminPermissionManagement; import org.keycloak.services.resources.admin.permissions.AdminPermissions; -import org.keycloak.storage.UserStorageProviderModel; import org.keycloak.representations.idm.LDAPCapabilityRepresentation; import org.keycloak.utils.ReservedCharValidator; @@ -235,21 +230,19 @@ public class RealmAdminResource { @NoCache @Produces(MediaType.APPLICATION_JSON) @Path("default-default-client-scopes") - public List getDefaultDefaultClientScopes() { + public Stream getDefaultDefaultClientScopes() { return getDefaultClientScopes(true); } - private List getDefaultClientScopes(boolean defaultScope) { + private Stream getDefaultClientScopes(boolean defaultScope) { auth.clients().requireViewClientScopes(); - List defaults = new LinkedList<>(); - for (ClientScopeModel clientScope : realm.getDefaultClientScopes(defaultScope)) { + return realm.getDefaultClientScopesStream(defaultScope).map(clientScope -> { ClientScopeRepresentation rep = new ClientScopeRepresentation(); rep.setId(clientScope.getId()); rep.setName(clientScope.getName()); - defaults.add(rep); - } - return defaults; + return rep; + }); } @@ -298,7 +291,7 @@ public class RealmAdminResource { @NoCache @Produces(MediaType.APPLICATION_JSON) @Path("default-optional-client-scopes") - public List getDefaultOptionalClientScopes() { + public Stream getDefaultOptionalClientScopes() { return getDefaultClientScopes(false); } @@ -432,11 +425,9 @@ public class RealmAdminResource { RepresentationToModel.updateRealm(rep, realm, session); // Refresh periodic sync tasks for configured federationProviders - List federationProviders = realm.getUserStorageProviders(); UserStorageSyncManager usersSyncManager = new UserStorageSyncManager(); - for (final UserStorageProviderModel fedProvider : federationProviders) { - usersSyncManager.notifyToRefreshPeriodicSync(session, realm, fedProvider, false); - } + realm.getUserStorageProvidersStream().forEachOrdered(fedProvider -> + usersSyncManager.notifyToRefreshPeriodicSync(session, realm, fedProvider, false)); adminEvent.operation(OperationType.UPDATE).representation(StripSecretsUtils.strip(rep)).success(); @@ -616,7 +607,7 @@ public class RealmAdminResource { @GET @NoCache @Produces(MediaType.APPLICATION_JSON) - public List> getClientSessionStats() { + public Stream> getClientSessionStats() { auth.realm().requireViewRealm(); Map> data = new HashMap<>(); @@ -651,10 +642,8 @@ public class RealmAdminResource { map.put("offline", entry.getValue().toString()); } } - List> result = new LinkedList<>(); - for (Map item : data.values()) - result.add(item); - return result; + + return data.values().stream(); } /** @@ -724,7 +713,7 @@ public class RealmAdminResource { @GET @NoCache @Produces(MediaType.APPLICATION_JSON) - public List getEvents(@QueryParam("type") List types, @QueryParam("client") String client, + public Stream getEvents(@QueryParam("type") List types, @QueryParam("client") String client, @QueryParam("user") String user, @QueryParam("dateFrom") String dateFrom, @QueryParam("dateTo") String dateTo, @QueryParam("ipAddress") String ipAddress, @QueryParam("first") Integer firstResult, @QueryParam("max") Integer maxResults) { @@ -783,15 +772,7 @@ public class RealmAdminResource { query.maxResults(Constants.DEFAULT_MAX_RESULTS); } - return toEventListRep(query.getResultList()); - } - - private List toEventListRep(List events) { - List reps = new ArrayList<>(); - for (Event event : events) { - reps.add(ModelToRepresentation.toRepresentation(event)); - } - return reps; + return query.getResultStream().map(ModelToRepresentation::toRepresentation); } /** @@ -815,7 +796,7 @@ public class RealmAdminResource { @GET @NoCache @Produces(MediaType.APPLICATION_JSON) - public List getEvents(@QueryParam("operationTypes") List operationTypes, @QueryParam("authRealm") String authRealm, @QueryParam("authClient") String authClient, + public Stream getEvents(@QueryParam("operationTypes") List operationTypes, @QueryParam("authRealm") String authRealm, @QueryParam("authClient") String authClient, @QueryParam("authUser") String authUser, @QueryParam("authIpAddress") String authIpAddress, @QueryParam("resourcePath") String resourcePath, @QueryParam("dateFrom") String dateFrom, @QueryParam("dateTo") String dateTo, @QueryParam("first") Integer firstResult, @@ -895,16 +876,7 @@ public class RealmAdminResource { query.maxResults(Constants.DEFAULT_MAX_RESULTS); } - return toAdminEventRep(query.getResultList()); - } - - private List toAdminEventRep(List events) { - List reps = new ArrayList<>(); - for (AdminEvent event : events) { - reps.add(ModelToRepresentation.toRepresentation(event)); - } - - return reps; + return query.getResultStream().map(ModelToRepresentation::toRepresentation); } /** @@ -1215,13 +1187,12 @@ public class RealmAdminResource { @Path("credential-registrators") @NoCache @Produces(javax.ws.rs.core.MediaType.APPLICATION_JSON) - public List getCredentialRegistrators(){ + public Stream getCredentialRegistrators(){ auth.realm().requireViewRealm(); - return session.getContext().getRealm().getRequiredActionProviders().stream() + return session.getContext().getRealm().getRequiredActionProvidersStream() .filter(ra -> ra.isEnabled()) .map(RequiredActionProviderModel::getProviderId) - .filter(providerId -> session.getProvider(RequiredActionProvider.class, providerId) instanceof CredentialRegistrator) - .collect(Collectors.toList()); + .filter(providerId -> session.getProvider(RequiredActionProvider.class, providerId) instanceof CredentialRegistrator); } } diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RealmsAdminResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RealmsAdminResource.java index 01caadfd16..6d9d4712b5 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/RealmsAdminResource.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/RealmsAdminResource.java @@ -49,8 +49,10 @@ import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import java.net.URI; -import java.util.ArrayList; -import java.util.List; +import java.util.*; +import java.util.stream.Stream; + +import static org.keycloak.utils.StreamsUtil.throwIfEmpty; /** * Top level resource for Admin REST API @@ -91,28 +93,22 @@ public class RealmsAdminResource { @GET @NoCache @Produces(MediaType.APPLICATION_JSON) - public List getRealms() { - List reps = new ArrayList(); - List realms = session.realms().getRealms(); - for (RealmModel realm : realms) { - addRealmRep(reps, realm); - } - if (reps.isEmpty()) { - throw new ForbiddenException(); - } - - logger.debug(("getRealms()")); - return reps; + public Stream getRealms() { + Stream realms = session.realms().getRealmsStream() + .map(this::toRealmRep) + .filter(Objects::nonNull); + return throwIfEmpty(realms, new ForbiddenException()); } - protected void addRealmRep(List reps, RealmModel realm) { + protected RealmRepresentation toRealmRep(RealmModel realm) { if (AdminPermissions.realms(session, auth).canView(realm)) { - reps.add(ModelToRepresentation.toRepresentation(realm, false)); + return ModelToRepresentation.toRepresentation(realm, false); } else if (AdminPermissions.realms(session, auth).isAdmin(realm)) { RealmRepresentation rep = new RealmRepresentation(); rep.setRealm(realm.getName()); - reps.add(rep); + return rep; } + return null; } /** diff --git a/services/src/main/java/org/keycloak/services/resources/admin/UserResource.java b/services/src/main/java/org/keycloak/services/resources/admin/UserResource.java index 9cdd49ecc4..43d654e072 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/UserResource.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/UserResource.java @@ -373,13 +373,12 @@ public class UserResource { private List getFederatedIdentities(UserModel user) { Set identities = session.users().getFederatedIdentities(user, realm); List result = new ArrayList(); + Set idps = realm.getIdentityProvidersStream().map(IdentityProviderModel::getAlias).collect(Collectors.toSet()); for (FederatedIdentityModel identity : identities) { - for (IdentityProviderModel identityProviderModel : realm.getIdentityProviders()) { - if (identityProviderModel.getAlias().equals(identity.getIdentityProvider())) { - FederatedIdentityRepresentation rep = ModelToRepresentation.toRepresentation(identity); - result.add(rep); - } + if (idps.contains(identity.getIdentityProvider())) { + FederatedIdentityRepresentation rep = ModelToRepresentation.toRepresentation(identity); + result.add(rep); } } return result; diff --git a/services/src/main/java/org/keycloak/services/resources/admin/permissions/MgmtPermissions.java b/services/src/main/java/org/keycloak/services/resources/admin/permissions/MgmtPermissions.java index c38cdae145..c12f455b91 100644 --- a/services/src/main/java/org/keycloak/services/resources/admin/permissions/MgmtPermissions.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/permissions/MgmtPermissions.java @@ -366,10 +366,7 @@ class MgmtPermissions implements AdminPermissionEvaluator, AdminPermissionManage if (identity.hasRealmRole(AdminRoles.ADMIN) || identity.hasRealmRole(AdminRoles.CREATE_REALM)) { return true; } - for (RealmModel realm : session.realms().getRealms()) { - if (isAdmin(realm)) return true; - } - return false; + return session.realms().getRealmsStream().anyMatch(this::isAdmin); } else { return isAdmin(adminsRealm); } diff --git a/services/src/main/java/org/keycloak/services/scheduled/ClearExpiredEvents.java b/services/src/main/java/org/keycloak/services/scheduled/ClearExpiredEvents.java index efef0f391c..aba77bf618 100755 --- a/services/src/main/java/org/keycloak/services/scheduled/ClearExpiredEvents.java +++ b/services/src/main/java/org/keycloak/services/scheduled/ClearExpiredEvents.java @@ -19,7 +19,6 @@ package org.keycloak.services.scheduled; import org.keycloak.events.EventStoreProvider; import org.keycloak.models.KeycloakSession; -import org.keycloak.models.RealmModel; import org.keycloak.timer.ScheduledTask; /** @@ -31,12 +30,12 @@ public class ClearExpiredEvents implements ScheduledTask { public void run(KeycloakSession session) { EventStoreProvider eventStore = session.getProvider(EventStoreProvider.class); if (eventStore != null) { - for (RealmModel realm : session.realms().getRealms()) { + session.realms().getRealmsStream().forEach(realm -> { if (realm.isEventsEnabled() && realm.getEventsExpiration() > 0) { long olderThan = System.currentTimeMillis() - realm.getEventsExpiration() * 1000; eventStore.clear(realm.getId(), olderThan); } - } + }); } } diff --git a/services/src/main/java/org/keycloak/services/scheduled/ClearExpiredUserSessions.java b/services/src/main/java/org/keycloak/services/scheduled/ClearExpiredUserSessions.java index 4ebd599a66..7678ee2c4c 100755 --- a/services/src/main/java/org/keycloak/services/scheduled/ClearExpiredUserSessions.java +++ b/services/src/main/java/org/keycloak/services/scheduled/ClearExpiredUserSessions.java @@ -18,7 +18,6 @@ package org.keycloak.services.scheduled; import org.keycloak.models.KeycloakSession; -import org.keycloak.models.RealmModel; import org.keycloak.models.UserSessionProvider; import org.keycloak.models.session.UserSessionPersisterProvider; import org.keycloak.timer.ScheduledTask; @@ -33,11 +32,11 @@ public class ClearExpiredUserSessions implements ScheduledTask { @Override public void run(KeycloakSession session) { UserSessionProvider sessions = session.sessions(); - for (RealmModel realm : session.realms().getRealms()) { + session.realms().getRealmsStream().forEach(realm -> { sessions.removeExpired(realm); session.authenticationSessions().removeExpired(realm); session.getProvider(UserSessionPersisterProvider.class).removeExpired(realm); - } + }); } } diff --git a/services/src/main/java/org/keycloak/services/util/ObjectMapperResolver.java b/services/src/main/java/org/keycloak/services/util/ObjectMapperResolver.java index ebeee69045..416129d683 100755 --- a/services/src/main/java/org/keycloak/services/util/ObjectMapperResolver.java +++ b/services/src/main/java/org/keycloak/services/util/ObjectMapperResolver.java @@ -36,9 +36,14 @@ import java.util.stream.Stream; * @version $Revision: 1 $ */ public class ObjectMapperResolver implements ContextResolver { - protected ObjectMapper mapper = new ObjectMapper(); + protected ObjectMapper mapper; public ObjectMapperResolver() { + mapper = createStreamSerializer(); + } + + public static ObjectMapper createStreamSerializer() { + ObjectMapper mapper = new ObjectMapper(); JavaType type = TypeFactory.unknownType(); JavaType streamType = mapper.getTypeFactory().constructParametricType(Stream.class, type); @@ -50,6 +55,8 @@ public class ObjectMapperResolver implements ContextResolver { if (Boolean.parseBoolean(System.getProperty("keycloak.jsonPrettyPrint", "false"))) { mapper.enable(SerializationFeature.INDENT_OUTPUT); } + + return mapper; } @Override diff --git a/services/src/main/java/org/keycloak/storage/ClientStorageManager.java b/services/src/main/java/org/keycloak/storage/ClientStorageManager.java index 2946ee184e..aa30dcc606 100644 --- a/services/src/main/java/org/keycloak/storage/ClientStorageManager.java +++ b/services/src/main/java/org/keycloak/storage/ClientStorageManager.java @@ -30,8 +30,7 @@ import org.keycloak.storage.client.ClientStorageProviderFactory; import org.keycloak.storage.client.ClientStorageProviderModel; import org.keycloak.utils.ServicesUtils; -import java.util.LinkedList; -import java.util.List; +import java.util.Objects; import java.util.stream.Stream; /** @@ -68,8 +67,18 @@ public class ClientStorageManager implements ClientProvider { } - public static List getStorageProviders(RealmModel realm) { - return realm.getClientStorageProviders(); + private static Stream getStorageProviders(RealmModel realm, KeycloakSession session, Class type) { + return realm.getClientStorageProvidersStream() + .filter(model -> { + ClientStorageProviderFactory factory = getClientStorageProviderFactory(model, session); + if (factory == null) { + logger.warnv("Configured ClientStorageProvider {0} of provider id {1} does not exist in realm {2}", + model.getName(), model.getProviderId(), realm.getName()); + return false; + } else { + return Types.supports(type, factory, ClientStorageProviderFactory.class); + } + }); } public static ClientStorageProvider getStorageProviderInstance(KeycloakSession session, ClientStorageProviderModel model, ClientStorageProviderFactory factory) { @@ -85,40 +94,21 @@ public class ClientStorageManager implements ClientProvider { } - public static List getStorageProviders(KeycloakSession session, RealmModel realm, Class type) { - List list = new LinkedList<>(); - for (ClientStorageProviderModel model : getStorageProviders(realm)) { - ClientStorageProviderFactory factory = (ClientStorageProviderFactory) session.getKeycloakSessionFactory().getProviderFactory(ClientStorageProvider.class, model.getProviderId()); - if (factory == null) { - logger.warnv("Configured ClientStorageProvider {0} of provider id {1} does not exist in realm {2}", model.getName(), model.getProviderId(), realm.getName()); - continue; - } - if (Types.supports(type, factory, ClientStorageProviderFactory.class)) { - list.add(type.cast(getStorageProviderInstance(session, model, factory))); - } + public static Stream getStorageProviders(KeycloakSession session, RealmModel realm, Class type) { + return getStorageProviders(realm, session, type) + .map(model -> type.cast(getStorageProviderInstance(session, model, getClientStorageProviderFactory(model, session)))); + } - - } - return list; + private static ClientStorageProviderFactory getClientStorageProviderFactory(ClientStorageProviderModel model, KeycloakSession session) { + return (ClientStorageProviderFactory) session.getKeycloakSessionFactory() + .getProviderFactory(ClientStorageProvider.class, model.getProviderId()); } - public static List getEnabledStorageProviders(KeycloakSession session, RealmModel realm, Class type) { - List list = new LinkedList<>(); - for (ClientStorageProviderModel model : getStorageProviders(realm)) { - if (!model.isEnabled()) continue; - ClientStorageProviderFactory factory = (ClientStorageProviderFactory) session.getKeycloakSessionFactory().getProviderFactory(ClientStorageProvider.class, model.getProviderId()); - if (factory == null) { - logger.warnv("Configured ClientStorageProvider {0} of provider id {1} does not exist in realm {2}", model.getName(), model.getProviderId(), realm.getName()); - continue; - } - if (Types.supports(type, factory, ClientStorageProviderFactory.class)) { - list.add(type.cast(getStorageProviderInstance(session, model, factory))); - } - - - } - return list; + public static Stream getEnabledStorageProviders(KeycloakSession session, RealmModel realm, Class type) { + return getStorageProviders(realm, session, type) + .filter(ClientStorageProviderModel::isEnabled) + .map(model -> type.cast(getStorageProviderInstance(session, model, getClientStorageProviderFactory(model, session)))); } @@ -145,11 +135,11 @@ public class ClientStorageManager implements ClientProvider { if (client != null) { return client; } - for (ClientLookupProvider provider : getEnabledStorageProviders(session, realm, ClientLookupProvider.class)) { - client = provider.getClientByClientId(realm, clientId); - if (client != null) return client; - } - return null; + return getEnabledStorageProviders(session, realm, ClientLookupProvider.class) + .map(provider -> provider.getClientByClientId(realm, clientId)) + .filter(Objects::nonNull) + .findFirst() + .orElse(null); } /** @@ -162,7 +152,7 @@ public class ClientStorageManager implements ClientProvider { @Override public Stream searchClientsByClientIdStream(RealmModel realm, String clientId, Integer firstResult, Integer maxResults) { Stream local = session.clientLocalStorage().searchClientsByClientIdStream(realm, clientId, firstResult, maxResults); - Stream ext = getEnabledStorageProviders(session, realm, ClientLookupProvider.class).stream() + Stream ext = getEnabledStorageProviders(session, realm, ClientLookupProvider.class) .flatMap(ServicesUtils.timeBound(session, clientStorageProviderTimeout, p -> ((ClientLookupProvider) p).searchClientsByClientIdStream(realm, clientId, firstResult, maxResults))); diff --git a/services/src/main/java/org/keycloak/storage/RoleStorageManager.java b/services/src/main/java/org/keycloak/storage/RoleStorageManager.java index e75884b5b5..fc73ffc0c7 100644 --- a/services/src/main/java/org/keycloak/storage/RoleStorageManager.java +++ b/services/src/main/java/org/keycloak/storage/RoleStorageManager.java @@ -16,8 +16,7 @@ */ package org.keycloak.storage; -import java.util.LinkedList; -import java.util.List; +import java.util.Objects; import java.util.stream.Stream; import org.jboss.logging.Logger; import org.keycloak.common.util.reflections.Types; @@ -69,8 +68,23 @@ public class RoleStorageManager implements RoleProvider { } - public static List getStorageProviders(RealmModel realm) { - return realm.getRoleStorageProviders(); + public static Stream getStorageProviders(RealmModel realm, KeycloakSession session, Class type) { + return realm.getRoleStorageProvidersStream() + .filter(model -> { + RoleStorageProviderFactory factory = getRoleStorageProviderFactory(model, session); + if (factory == null) { + logger.warnv("Configured RoleStorageProvider {0} of provider id {1} does not exist in realm {2}", + model.getName(), model.getProviderId(), realm.getName()); + return false; + } else { + return Types.supports(type, factory, RoleStorageProviderFactory.class); + } + }); + } + + private static RoleStorageProviderFactory getRoleStorageProviderFactory(RoleStorageProviderModel model, KeycloakSession session) { + return (RoleStorageProviderFactory) session.getKeycloakSessionFactory() + .getProviderFactory(RoleStorageProvider.class, model.getProviderId()); } public static RoleStorageProvider getStorageProviderInstance(KeycloakSession session, RoleStorageProviderModel model, RoleStorageProviderFactory factory) { @@ -86,38 +100,16 @@ public class RoleStorageManager implements RoleProvider { } - public static List getStorageProviders(KeycloakSession session, RealmModel realm, Class type) { - List list = new LinkedList<>(); - for (RoleStorageProviderModel model : getStorageProviders(realm)) { - RoleStorageProviderFactory factory = (RoleStorageProviderFactory) session.getKeycloakSessionFactory().getProviderFactory(RoleStorageProvider.class, model.getProviderId()); - if (factory == null) { - logger.warnv("Configured RoleStorageProvider {0} of provider id {1} does not exist in realm {2}", model.getName(), model.getProviderId(), realm.getName()); - continue; - } - if (Types.supports(type, factory, RoleStorageProviderFactory.class)) { - list.add(type.cast(getStorageProviderInstance(session, model, factory))); - } - - - } - return list; + public static Stream getStorageProviders(KeycloakSession session, RealmModel realm, Class type) { + return getStorageProviders(realm, session, type) + .map(model -> type.cast(getStorageProviderInstance(session, model, getRoleStorageProviderFactory(model, session)))); } - public static List getEnabledStorageProviders(KeycloakSession session, RealmModel realm, Class type) { - List list = new LinkedList<>(); - for (RoleStorageProviderModel model : getStorageProviders(realm)) { - if (!model.isEnabled()) continue; - RoleStorageProviderFactory factory = (RoleStorageProviderFactory) session.getKeycloakSessionFactory().getProviderFactory(RoleStorageProvider.class, model.getProviderId()); - if (factory == null) { - logger.warnv("Configured RoleStorageProvider {0} of provider id {1} does not exist in realm {2}", model.getName(), model.getProviderId(), realm.getName()); - continue; - } - if (Types.supports(type, factory, RoleStorageProviderFactory.class)) { - list.add(type.cast(getStorageProviderInstance(session, model, factory))); - } - } - return list; + public static Stream getEnabledStorageProviders(KeycloakSession session, RealmModel realm, Class type) { + return getStorageProviders(realm, session, type) + .filter(RoleStorageProviderModel::isEnabled) + .map(model -> type.cast(getStorageProviderInstance(session, model, getRoleStorageProviderFactory(model, session)))); } @Override @@ -134,11 +126,11 @@ public class RoleStorageManager implements RoleProvider { public RoleModel getRealmRole(RealmModel realm, String name) { RoleModel realmRole = session.roleLocalStorage().getRealmRole(realm, name); if (realmRole != null) return realmRole; - for (RoleLookupProvider enabledStorageProvider : getEnabledStorageProviders(session, realm, RoleLookupProvider.class)) { - realmRole = enabledStorageProvider.getRealmRole(realm, name); - if (realmRole != null) return realmRole; - } - return null; + return getEnabledStorageProviders(session, realm, RoleLookupProvider.class) + .map(provider -> provider.getRealmRole(realm, name)) + .filter(Objects::nonNull) + .findFirst() + .orElse(null); } @Override @@ -168,7 +160,7 @@ public class RoleStorageManager implements RoleProvider { @Override public Stream searchForRolesStream(RealmModel realm, String search, Integer first, Integer max) { Stream local = session.roleLocalStorage().searchForRolesStream(realm, search, first, max); - Stream ext = getEnabledStorageProviders(session, realm, RoleLookupProvider.class).stream() + Stream ext = getEnabledStorageProviders(session, realm, RoleLookupProvider.class) .flatMap(ServicesUtils.timeBound(session, roleStorageProviderTimeout, p -> ((RoleLookupProvider) p).searchForRolesStream(realm, search, first, max))); @@ -208,11 +200,11 @@ public class RoleStorageManager implements RoleProvider { public RoleModel getClientRole(ClientModel client, String name) { RoleModel clientRole = session.roleLocalStorage().getClientRole(client, name); if (clientRole != null) return clientRole; - for (RoleLookupProvider enabledStorageProvider : getEnabledStorageProviders(session, client.getRealm(), RoleLookupProvider.class)) { - clientRole = enabledStorageProvider.getClientRole(client, name); - if (clientRole != null) return clientRole; - } - return null; + return getEnabledStorageProviders(session, client.getRealm(), RoleLookupProvider.class) + .map(provider -> provider.getClientRole(client, name)) + .filter(Objects::nonNull) + .findFirst() + .orElse(null); } @Override @@ -235,7 +227,7 @@ public class RoleStorageManager implements RoleProvider { @Override public Stream searchForClientRolesStream(ClientModel client, String search, Integer first, Integer max) { Stream local = session.roleLocalStorage().searchForClientRolesStream(client, search, first, max); - Stream ext = getEnabledStorageProviders(session, client.getRealm(), RoleLookupProvider.class).stream() + Stream ext = getEnabledStorageProviders(session, client.getRealm(), RoleLookupProvider.class) .flatMap(ServicesUtils.timeBound(session, roleStorageProviderTimeout, p -> ((RoleLookupProvider) p).searchForClientRolesStream(client, search, first, max))); diff --git a/services/src/main/java/org/keycloak/storage/UserStorageManager.java b/services/src/main/java/org/keycloak/storage/UserStorageManager.java index a50b56d86c..31d16c07a9 100755 --- a/services/src/main/java/org/keycloak/storage/UserStorageManager.java +++ b/services/src/main/java/org/keycloak/storage/UserStorageManager.java @@ -58,8 +58,11 @@ import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.TreeSet; +import java.util.stream.Collectors; +import java.util.stream.Stream; import static org.keycloak.models.utils.KeycloakModelUtils.runJobInTransaction; @@ -86,8 +89,18 @@ public class UserStorageManager implements UserProvider, OnUserCache, OnCreateCo return session.userLocalStorage(); } - public static List getStorageProviders(RealmModel realm) { - return realm.getUserStorageProviders(); + public static Stream getStorageProviders(RealmModel realm, KeycloakSession session, Class type) { + return realm.getUserStorageProvidersStream() + .filter(model -> { + UserStorageProviderFactory factory = getUserStorageProviderFactory(model, session); + if (factory == null) { + logger.warnv("Configured UserStorageProvider {0} of provider id {1} does not exist in realm {2}", + model.getName(), model.getProviderId(), realm.getName()); + return false; + } else { + return Types.supports(type, factory, UserStorageProviderFactory.class); + } + }); } public static UserStorageProvider getStorageProviderInstance(KeycloakSession session, UserStorageProviderModel model, UserStorageProviderFactory factory) { @@ -103,40 +116,21 @@ public class UserStorageManager implements UserProvider, OnUserCache, OnCreateCo } - public static List getStorageProviders(KeycloakSession session, RealmModel realm, Class type) { - List list = new LinkedList<>(); - for (UserStorageProviderModel model : getStorageProviders(realm)) { - UserStorageProviderFactory factory = (UserStorageProviderFactory) session.getKeycloakSessionFactory().getProviderFactory(UserStorageProvider.class, model.getProviderId()); - if (factory == null) { - logger.warnv("Configured UserStorageProvider {0} of provider id {1} does not exist in realm {2}", model.getName(), model.getProviderId(), realm.getName()); - continue; - } - if (Types.supports(type, factory, UserStorageProviderFactory.class)) { - list.add(type.cast(getStorageProviderInstance(session, model, factory))); - } + public static Stream getStorageProviders(KeycloakSession session, RealmModel realm, Class type) { + return getStorageProviders(realm, session, type) + .map(model -> type.cast(getStorageProviderInstance(session, model, getUserStorageProviderFactory(model, session)))); + } - - } - return list; + private static UserStorageProviderFactory getUserStorageProviderFactory(UserStorageProviderModel model, KeycloakSession session) { + return (UserStorageProviderFactory) session.getKeycloakSessionFactory() + .getProviderFactory(UserStorageProvider.class, model.getProviderId()); } - public static List getEnabledStorageProviders(KeycloakSession session, RealmModel realm, Class type) { - List list = new LinkedList<>(); - for (UserStorageProviderModel model : getStorageProviders(realm)) { - if (!model.isEnabled()) continue; - UserStorageProviderFactory factory = (UserStorageProviderFactory) session.getKeycloakSessionFactory().getProviderFactory(UserStorageProvider.class, model.getProviderId()); - if (factory == null) { - logger.warnv("Configured UserStorageProvider {0} of provider id {1} does not exist in realm {2}", model.getName(), model.getProviderId(), realm.getName()); - continue; - } - if (Types.supports(type, factory, UserStorageProviderFactory.class)) { - list.add(type.cast(getStorageProviderInstance(session, model, factory))); - } - - - } - return list; + public static Stream getEnabledStorageProviders(KeycloakSession session, RealmModel realm, Class type) { + return getStorageProviders(realm, session, type) + .filter(UserStorageProviderModel::isEnabled) + .map(model -> type.cast(getStorageProviderInstance(session, model, getUserStorageProviderFactory(model, session)))); } @@ -147,12 +141,13 @@ public class UserStorageManager implements UserProvider, OnUserCache, OnCreateCo @Override public UserModel addUser(RealmModel realm, String username) { - for (UserRegistrationProvider provider : getEnabledStorageProviders(session, realm, UserRegistrationProvider.class)) { - UserModel user = provider.addUser(realm, username); - if (user != null) return user; - } + UserModel user = getEnabledStorageProviders(session, realm, UserRegistrationProvider.class) + .map(provider -> provider.addUser(realm, username)) + .filter(Objects::nonNull) + .findFirst() + .orElse(null); - return localStorage().addUser(realm, username.toLowerCase()); + return user == null ? localStorage().addUser(realm, username.toLowerCase()) : user; } public static UserStorageProviderModel getStorageProviderModel(RealmModel realm, String componentId) { @@ -404,11 +399,11 @@ public class UserStorageManager implements UserProvider, OnUserCache, OnCreateCo if (user != null) { return importValidation(realm, user); } - for (UserLookupProvider provider : getEnabledStorageProviders(session, realm, UserLookupProvider.class)) { - user = provider.getUserByUsername(username, realm); - if (user != null) return user; - } - return null; + return getEnabledStorageProviders(session, realm, UserLookupProvider.class) + .map(provider -> provider.getUserByUsername(username, realm)) + .filter(Objects::nonNull) + .findFirst() + .orElse(null); } @Override @@ -421,13 +416,11 @@ public class UserStorageManager implements UserProvider, OnUserCache, OnCreateCo return user; } } - for (UserLookupProvider provider : getEnabledStorageProviders(session, realm, UserLookupProvider.class)) { - user = provider.getUserByEmail(email, realm); - if (user != null) { - return user; - } - } - return null; + return getEnabledStorageProviders(session, realm, UserLookupProvider.class) + .map(provider -> provider.getUserByEmail(email, realm)) + .filter(Objects::nonNull) + .findFirst() + .orElse(null); } @Override @@ -466,10 +459,9 @@ public class UserStorageManager implements UserProvider, OnUserCache, OnCreateCo @Override public int getUsersCount(RealmModel realm, boolean includeServiceAccount) { int size = localStorage().getUsersCount(realm, includeServiceAccount); - for (UserQueryProvider provider : getEnabledStorageProviders(session, realm, UserQueryProvider.class)) { - size += provider.getUsersCount(realm); - } - return size; + return getEnabledStorageProviders(session, realm, UserQueryProvider.class) + .map(provider -> provider.getUsersCount(realm)) + .reduce(size, Integer::sum); } @Override @@ -512,7 +504,8 @@ public class UserStorageManager implements UserProvider, OnUserCache, OnCreateCo if (firstResult < 0) firstResult = 0; if (maxResults < 0) maxResults = Integer.MAX_VALUE - 1; - List storageProviders = getEnabledStorageProviders(session, realm, UserQueryProvider.class); + List storageProviders = getEnabledStorageProviders(session, realm, UserQueryProvider.class) + .collect(Collectors.toList()); // we can skip rest of method if there are no storage providers if (storageProviders.isEmpty()) { return pagedQuery.query(localStorage(), firstResult, maxResults); @@ -661,13 +654,8 @@ public class UserStorageManager implements UserProvider, OnUserCache, OnCreateCo @Override public void grantToAllUsers(RealmModel realm, RoleModel role) { - List storageProviders = getEnabledStorageProviders(session, realm, UserBulkUpdateProvider.class); - LinkedList providers = new LinkedList<>(); - providers.add(localStorage()); - providers.addAll(storageProviders); - for (UserBulkUpdateProvider provider : providers) { - provider.grantToAllUsers(realm, role); - } + Stream.concat(Stream.of(localStorage()), getEnabledStorageProviders(session, realm, UserBulkUpdateProvider.class)) + .forEachOrdered(provider -> provider.grantToAllUsers(realm, role)); } @Override @@ -708,9 +696,8 @@ public class UserStorageManager implements UserProvider, OnUserCache, OnCreateCo localStorage().preRemove(realm); if (getFederatedStorage() != null) { getFederatedStorage().preRemove(realm); - for (UserStorageProvider provider : getEnabledStorageProviders(session, realm, UserStorageProvider.class)) { - provider.preRemove(realm); - } + getEnabledStorageProviders(session, realm, UserStorageProvider.class) + .forEachOrdered(provider -> provider.preRemove(realm)); } } @@ -719,9 +706,8 @@ public class UserStorageManager implements UserProvider, OnUserCache, OnCreateCo localStorage().preRemove(realm, group); if (getFederatedStorage() != null) { getFederatedStorage().preRemove(realm, group); - for (UserStorageProvider provider : getEnabledStorageProviders(session, realm, UserStorageProvider.class)) { - provider.preRemove(realm, group); - } + getEnabledStorageProviders(session, realm, UserStorageProvider.class) + .forEachOrdered(provider -> provider.preRemove(realm, group)); } } @@ -730,9 +716,8 @@ public class UserStorageManager implements UserProvider, OnUserCache, OnCreateCo localStorage().preRemove(realm, role); if (getFederatedStorage() != null) { getFederatedStorage().preRemove(realm, role); - for (UserStorageProvider provider : getEnabledStorageProviders(session, realm, UserStorageProvider.class)) { - provider.preRemove(realm, role); - } + getEnabledStorageProviders(session, realm, UserStorageProvider.class) + .forEachOrdered(provider -> provider.preRemove(realm, role)); } } diff --git a/services/src/main/java/org/keycloak/storage/openshift/OpenshiftSAClientAdapter.java b/services/src/main/java/org/keycloak/storage/openshift/OpenshiftSAClientAdapter.java index 0f084afca2..fc8552a429 100644 --- a/services/src/main/java/org/keycloak/storage/openshift/OpenshiftSAClientAdapter.java +++ b/services/src/main/java/org/keycloak/storage/openshift/OpenshiftSAClientAdapter.java @@ -22,6 +22,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.function.Consumer; import java.util.function.Supplier; @@ -389,8 +390,10 @@ public final class OpenshiftSAClientAdapter extends AbstractReadOnlyClientStorag } private ClientScopeModel createClientScope(String scope) { - ClientScopeModel managedScope = realm.getClientScopes().stream().filter(scopeModel -> scopeModel.getName().equals(scope)) - .findAny().orElse(null); + ClientScopeModel managedScope = realm.getClientScopesStream() + .filter(scopeModel -> Objects.equals(scopeModel.getName(), scope)) + .findAny() + .orElse(null); if (managedScope != null) { return managedScope; diff --git a/services/src/main/java/org/keycloak/theme/beans/LocaleBean.java b/services/src/main/java/org/keycloak/theme/beans/LocaleBean.java index ad4062d2e1..2c163df61b 100755 --- a/services/src/main/java/org/keycloak/theme/beans/LocaleBean.java +++ b/services/src/main/java/org/keycloak/theme/beans/LocaleBean.java @@ -20,9 +20,9 @@ package org.keycloak.theme.beans; import org.keycloak.models.RealmModel; import javax.ws.rs.core.UriBuilder; -import java.util.LinkedList; import java.util.List; import java.util.Properties; +import java.util.stream.Collectors; /** * @author Stian Thorgersen @@ -37,12 +37,13 @@ public class LocaleBean { this.currentLanguageTag = current.toLanguageTag(); this.current = messages.getProperty("locale_" + this.currentLanguageTag, this.currentLanguageTag); - supported = new LinkedList<>(); - for (String l : realm.getSupportedLocales()) { - String label = messages.getProperty("locale_" + l, l); - String url = uriBuilder.replaceQueryParam("kc_locale", l).build().toString(); - supported.add(new Locale(l, label, url)); - } + supported = realm.getSupportedLocalesStream() + .map(l -> { + String label = messages.getProperty("locale_" + l, l); + String url = uriBuilder.replaceQueryParam("kc_locale", l).build().toString(); + return new Locale(l, label, url); + }) + .collect(Collectors.toList()); } public String getCurrent() { diff --git a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/TestingResourceProvider.java b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/TestingResourceProvider.java index f99d00dc36..6c4f2c207b 100644 --- a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/TestingResourceProvider.java +++ b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/TestingResourceProvider.java @@ -100,12 +100,13 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.text.ParseException; import java.text.SimpleDateFormat; -import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; +import java.util.stream.Collectors; +import java.util.stream.Stream; /** * @author Stian Thorgersen @@ -309,10 +310,10 @@ public class TestingResourceProvider implements RealmResourceProvider { @GET @NoCache @Produces(MediaType.APPLICATION_JSON) - public List queryEvents(@QueryParam("realmId") String realmId, @QueryParam("type") List types, @QueryParam("client") String client, - @QueryParam("user") String user, @QueryParam("dateFrom") String dateFrom, @QueryParam("dateTo") String dateTo, - @QueryParam("ipAddress") String ipAddress, @QueryParam("first") Integer firstResult, - @QueryParam("max") Integer maxResults) { + public Stream queryEvents(@QueryParam("realmId") String realmId, @QueryParam("type") List types, @QueryParam("client") String client, + @QueryParam("user") String user, @QueryParam("dateFrom") String dateFrom, @QueryParam("dateTo") String dateTo, + @QueryParam("ipAddress") String ipAddress, @QueryParam("first") Integer firstResult, + @QueryParam("max") Integer maxResults) { EventStoreProvider eventStore = session.getProvider(EventStoreProvider.class); @@ -358,15 +359,7 @@ public class TestingResourceProvider implements RealmResourceProvider { query.maxResults(maxResults); } - return toEventListRep(query.getResultList()); - } - - private List toEventListRep(List events) { - List reps = new ArrayList<>(); - for (Event event : events) { - reps.add(ModelToRepresentation.toRepresentation(event)); - } - return reps; + return query.getResultStream().map(ModelToRepresentation::toRepresentation); } @PUT @@ -441,7 +434,7 @@ public class TestingResourceProvider implements RealmResourceProvider { @GET @NoCache @Produces(MediaType.APPLICATION_JSON) - public List getAdminEvents(@QueryParam("realmId") String realmId, @QueryParam("operationTypes") List operationTypes, @QueryParam("authRealm") String authRealm, @QueryParam("authClient") String authClient, + public Stream getAdminEvents(@QueryParam("realmId") String realmId, @QueryParam("operationTypes") List operationTypes, @QueryParam("authRealm") String authRealm, @QueryParam("authClient") String authClient, @QueryParam("authUser") String authUser, @QueryParam("authIpAddress") String authIpAddress, @QueryParam("resourcePath") String resourcePath, @QueryParam("dateFrom") String dateFrom, @QueryParam("dateTo") String dateTo, @QueryParam("first") Integer firstResult, @@ -503,7 +496,7 @@ public class TestingResourceProvider implements RealmResourceProvider { query.maxResults(maxResults); } - return toAdminEventRep(query.getResultList()); + return query.getResultStream().map(ModelToRepresentation::toRepresentation); } private Date formatDate(String date, String paramName) { @@ -515,15 +508,6 @@ public class TestingResourceProvider implements RealmResourceProvider { } } - private List toAdminEventRep(List events) { - List reps = new ArrayList<>(); - for (AdminEvent event : events) { - reps.add(ModelToRepresentation.toRepresentation(event)); - } - - return reps; - } - @POST @Path("/on-admin-event") @Consumes(MediaType.APPLICATION_JSON) @@ -677,17 +661,16 @@ public class TestingResourceProvider implements RealmResourceProvider { @Path("/test-component") @Produces(MediaType.APPLICATION_JSON) public Map getTestComponentDetails() { - Map reps = new HashMap<>(); - RealmModel realm = session.getContext().getRealm(); - for (ComponentModel c : realm.getComponents(realm.getId(), TestProvider.class.getName())) { - ProviderFactory f = session.getKeycloakSessionFactory().getProviderFactory(TestProvider.class, c.getProviderId()); - TestProviderFactory factory = (TestProviderFactory) f; - TestProvider p = (TestProvider) factory.create(session, c); - reps.put(c.getName(), p.getDetails()); - } - - return reps; + return realm.getComponentsStream(realm.getId(), TestProvider.class.getName()) + .collect(Collectors.toMap(ComponentModel::getName, + componentModel -> { + ProviderFactory f = session.getKeycloakSessionFactory() + .getProviderFactory(TestProvider.class, componentModel.getProviderId()); + TestProviderFactory factory = (TestProviderFactory) f; + TestProvider p = (TestProvider) factory.create(session, componentModel); + return p.getDetails(); + })); } diff --git a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/resource/TestLDAPResource.java b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/resource/TestLDAPResource.java index d6692f7368..96b6671e97 100644 --- a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/resource/TestLDAPResource.java +++ b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/resource/TestLDAPResource.java @@ -115,7 +115,7 @@ public class TestLDAPResource { LDAPTestUtils.addLocalUser(session, realm, "mary", "mary@test.com", "password-app"); LDAPTestUtils.addLocalUser(session, realm, "john", "john@test.com", "password-app"); - ComponentModel ldapModel = LDAPTestUtils.getLdapProviderModel(session, realm); + ComponentModel ldapModel = LDAPTestUtils.getLdapProviderModel(realm); LDAPStorageProvider ldapFedProvider = LDAPTestUtils.getLdapProvider(session, ldapModel); String descriptionAttrName = getGroupDescriptionLDAPAttrName(ldapFedProvider); @@ -187,7 +187,7 @@ public class TestLDAPResource { @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) public void prepareRolesLDAPTest() { - ComponentModel ldapModel = LDAPTestUtils.getLdapProviderModel(session, realm); + ComponentModel ldapModel = LDAPTestUtils.getLdapProviderModel(realm); LDAPStorageProvider ldapFedProvider = LDAPTestUtils.getLdapProvider(session, ldapModel); // Add role mapper @@ -232,7 +232,7 @@ public class TestLDAPResource { @Path("/remove-ldap-user") @Consumes(MediaType.APPLICATION_JSON) public void removeLDAPUser(@QueryParam("username") String ldapUsername) { - ComponentModel ldapCompModel = LDAPTestUtils.getLdapProviderModel(session, realm); + ComponentModel ldapCompModel = LDAPTestUtils.getLdapProviderModel(realm); UserStorageProviderModel ldapModel = new UserStorageProviderModel(ldapCompModel); LDAPStorageProvider ldapProvider = LDAPTestUtils.getLdapProvider(session, ldapModel); diff --git a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/util/LDAPTestUtils.java b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/util/LDAPTestUtils.java index 4a6d0ac27f..2aaf037505 100644 --- a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/util/LDAPTestUtils.java +++ b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/util/LDAPTestUtils.java @@ -44,12 +44,7 @@ import org.keycloak.storage.ldap.mappers.membership.role.RoleLDAPStorageMapper; import org.keycloak.storage.ldap.mappers.membership.role.RoleLDAPStorageMapperFactory; import org.keycloak.storage.ldap.mappers.membership.role.RoleMapperConfig; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; /** * @author Marek Posolda @@ -137,14 +132,11 @@ public class LDAPTestUtils { } } - public static ComponentModel getLdapProviderModel(KeycloakSession session, RealmModel realm) { - List components = realm.getComponents(realm.getId(), UserStorageProvider.class.getName()); - for (ComponentModel component : components) { - if (LDAPStorageProviderFactory.PROVIDER_NAME.equals(component.getProviderId())) { - return component; - } - } - return null; + public static ComponentModel getLdapProviderModel(RealmModel realm) { + return realm.getComponentsStream(realm.getId(), UserStorageProvider.class.getName()) + .filter(component -> Objects.equals(component.getProviderId(), LDAPStorageProviderFactory.PROVIDER_NAME)) + .findFirst() + .orElse(null); } public static LDAPStorageProvider getLdapProvider(KeycloakSession keycloakSession, ComponentModel ldapFedModel) { @@ -198,13 +190,10 @@ public class LDAPTestUtils { } public static ComponentModel getSubcomponentByName(RealmModel realm, ComponentModel providerModel, String name) { - List components = realm.getComponents(providerModel.getId(), LDAPStorageMapper.class.getName()); - for (ComponentModel component : components) { - if (component.getName().equals(name)) { - return component; - } - } - return null; + return realm.getComponentsStream(providerModel.getId(), LDAPStorageMapper.class.getName()) + .filter(component -> Objects.equals(name, component.getName())) + .findFirst() + .orElse(null); } public static void addOrUpdateGroupMapper(RealmModel realm, ComponentModel providerModel, LDAPGroupMapperMode mode, String descriptionAttrName, String... otherConfigOptions) { diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/SocialLoginTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/SocialLoginTest.java index 747f9f783b..969e638ed8 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/SocialLoginTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/SocialLoginTest.java @@ -16,7 +16,6 @@ import org.keycloak.common.Profile; import org.keycloak.models.ClientModel; import org.keycloak.models.IdentityProviderMapperModel; import org.keycloak.models.IdentityProviderMapperSyncMode; -import org.keycloak.models.IdentityProviderModel; import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; import org.keycloak.protocol.oidc.OIDCLoginProtocol; @@ -228,11 +227,10 @@ public class SocialLoginTest extends AbstractKeycloakTest { Policy clientPolicy = management.authz().getStoreFactory().getPolicyStore().create(clientPolicyRep, server); management.users().adminImpersonatingPermission().addAssociatedPolicy(clientPolicy); management.users().adminImpersonatingPermission().setDecisionStrategy(DecisionStrategy.AFFIRMATIVE); - for (IdentityProviderModel idp : realm.getIdentityProviders()) { + realm.getIdentityProvidersStream().forEach(idp -> { management.idps().setPermissionsEnabled(idp, true); management.idps().exchangeToPermission(idp).addAssociatedPolicy(clientPolicy); - } - + }); } @Test diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/ldap/LDAPLegacyImportTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/ldap/LDAPLegacyImportTest.java index fb2f334566..c7ab33ee64 100755 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/ldap/LDAPLegacyImportTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/ldap/LDAPLegacyImportTest.java @@ -78,7 +78,7 @@ public class LDAPLegacyImportTest extends AbstractLDAPTest { testingClient.server().run(session -> { LDAPTestContext ctx = LDAPTestContext.init(session); RealmModel appRealm = ctx.getRealm(); - ComponentModel ldapModel = appRealm.getComponents(appRealm.getId(), UserStorageProvider.class.getName()).get(0); + ComponentModel ldapModel = appRealm.getComponentsStream(appRealm.getId(), UserStorageProvider.class.getName()).findFirst().get(); LDAPTestUtils.addLocalUser(session, appRealm, "marykeycloak", "mary@test.com", "password-app"); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/ldap/LDAPNoCacheTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/ldap/LDAPNoCacheTest.java index 42c08174e6..d122e5f931 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/ldap/LDAPNoCacheTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/ldap/LDAPNoCacheTest.java @@ -30,7 +30,6 @@ import org.junit.FixMethodOrder; import org.junit.Rule; import org.junit.Test; import org.junit.runners.MethodSorters; -import org.keycloak.component.ComponentModel; import org.keycloak.models.KeycloakSession; import org.keycloak.models.LDAPConstants; import org.keycloak.models.RealmModel; @@ -89,11 +88,9 @@ public class LDAPNoCacheTest extends AbstractLDAPTest { appRealm.updateComponent(ctx.getLdapModel()); // Switch mappers to "Always read value from LDAP". Changed attributes in LDAP should be immediately visible on Keycloak side - List ldapMappers = appRealm.getComponents(ctx.getLdapModel().getId()); - ldapMappers.stream() + appRealm.getComponentsStream(ctx.getLdapModel().getId()) .filter(mapper -> UserAttributeLDAPStorageMapperFactory.PROVIDER_ID.equals(mapper.getProviderId())) .forEach(mapper -> { - mapper.put(UserAttributeLDAPStorageMapper.ALWAYS_READ_VALUE_FROM_LDAP, true); appRealm.updateComponent(mapper); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/ldap/LDAPNoMSADTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/ldap/LDAPNoMSADTest.java index b8831397f9..509da8ac80 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/ldap/LDAPNoMSADTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/ldap/LDAPNoMSADTest.java @@ -38,6 +38,7 @@ import org.keycloak.testsuite.util.LDAPTestConfiguration; import org.keycloak.testsuite.util.LDAPTestUtils; import java.util.List; +import java.util.Objects; import static org.hamcrest.Matchers.equalToIgnoringCase; @@ -110,13 +111,10 @@ public class LDAPNoMSADTest extends AbstractLDAPTest { Assert.assertEquals("sn=Doe2", john2.getDn().getFirstRdn().toString()); // Remove "sn" mapper - List components = appRealm.getComponents(ctx.getLdapModel().getId(), LDAPStorageMapper.class.getName()); - for (ComponentModel mapper : components) { - if (mapper.getName().equals("last name")) { - snMapper = mapper; - break; - } - } + snMapper = appRealm.getComponentsStream(ctx.getLdapModel().getId(), LDAPStorageMapper.class.getName()) + .filter(mapper -> Objects.equals(mapper.getName(), "last name")) + .findFirst() + .orElse(null); Assert.assertNotNull(snMapper); appRealm.removeComponent(snMapper); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/ldap/LDAPProvidersFullNameMapperTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/ldap/LDAPProvidersFullNameMapperTest.java index b561491a56..92a17956de 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/ldap/LDAPProvidersFullNameMapperTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/ldap/LDAPProvidersFullNameMapperTest.java @@ -69,7 +69,7 @@ public class LDAPProvidersFullNameMapperTest extends AbstractLDAPTest { Assert.assertNull(session.users().getUserByUsername("fullname", appRealm)); // Add the user with some fullName into LDAP directly. Ensure that fullName is saved into "cn" attribute in LDAP (currently mapped to model firstName) - ComponentModel ldapModel = LDAPTestUtils.getLdapProviderModel(session, appRealm); + ComponentModel ldapModel = LDAPTestUtils.getLdapProviderModel(appRealm); // add fullname mapper to the provider and remove "firstNameMapper". For this test, we will simply map full name to the LDAP attribute, which was before firstName ( "givenName" on active directory, "cn" on other LDAP servers) ComponentModel firstNameMapper = LDAPTestUtils.getSubcomponentByName(appRealm, ldapModel, "first name"); @@ -90,7 +90,7 @@ public class LDAPProvidersFullNameMapperTest extends AbstractLDAPTest { LDAPTestContext ctx = LDAPTestContext.init(session); RealmModel appRealm = ctx.getRealm(); - ComponentModel ldapModel = LDAPTestUtils.getLdapProviderModel(session, appRealm); + ComponentModel ldapModel = LDAPTestUtils.getLdapProviderModel(appRealm); LDAPStorageProvider ldapFedProvider = LDAPTestUtils.getLdapProvider(session, ldapModel); LDAPTestUtils.addLDAPUser(ldapFedProvider, appRealm, "fullname", "James", "Dee", "fullname@email.org", null, "4578"); @@ -129,7 +129,7 @@ public class LDAPProvidersFullNameMapperTest extends AbstractLDAPTest { LDAPTestContext ctx = LDAPTestContext.init(session); RealmModel appRealm = ctx.getRealm(); - ComponentModel ldapModel = LDAPTestUtils.getLdapProviderModel(session, appRealm); + ComponentModel ldapModel = LDAPTestUtils.getLdapProviderModel(appRealm); LDAPStorageProvider ldapFedProvider = LDAPTestUtils.getLdapProvider(session, ldapModel); LDAPTestUtils.addLDAPUser(ldapFedProvider, appRealm, "fullname", "James", "Dee", "fullname@email.org", null, "4578"); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/ldap/LDAPProvidersIntegrationTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/ldap/LDAPProvidersIntegrationTest.java index ae0559673a..d125bfc1cf 100755 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/ldap/LDAPProvidersIntegrationTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/ldap/LDAPProvidersIntegrationTest.java @@ -502,7 +502,7 @@ public class LDAPProvidersIntegrationTest extends AbstractLDAPTest { LDAPTestContext ctx = LDAPTestContext.init(session); RealmModel appRealm = ctx.getRealm(); - ComponentModel ldapModel = LDAPTestUtils.getLdapProviderModel(session, appRealm); + ComponentModel ldapModel = LDAPTestUtils.getLdapProviderModel(appRealm); LDAPStorageProvider ldapFedProvider = LDAPTestUtils.getLdapProvider(session, ldapModel); LDAPObject johnZip = LDAPTestUtils.addLDAPUser(ldapFedProvider, appRealm, "johnzip", "John", "Zip", "johnzip@email.org", null, "12398"); 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 6bd255e08d..3f54a695f9 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 @@ -35,7 +35,6 @@ import org.keycloak.models.utils.KeycloakModelUtils; import org.keycloak.representations.idm.ComponentRepresentation; import org.keycloak.representations.idm.SynchronizationResultRepresentation; import org.keycloak.services.managers.UserStorageSyncManager; -import org.keycloak.storage.UserStorageProviderModel; import org.keycloak.storage.ldap.LDAPStorageProvider; import org.keycloak.storage.ldap.LDAPStorageProviderFactory; import org.keycloak.storage.ldap.LDAPUtils; @@ -77,7 +76,7 @@ public class LDAPSyncTest extends AbstractLDAPTest { LDAPTestUtils.addOrUpdateGroupMapper(appRealm, ctx.getLdapModel(), LDAPGroupMapperMode.LDAP_ONLY, descriptionAttrName); // Remove all LDAP groups LDAPTestUtils.removeAllLDAPGroups(session, appRealm, ctx.getLdapModel(), "groupsMapper"); - ComponentModel ldapModel = LDAPTestUtils.getLdapProviderModel(session, appRealm); + ComponentModel ldapModel = LDAPTestUtils.getLdapProviderModel(appRealm); ldapModel.put(LDAPConstants.SYNC_REGISTRATIONS, "false"); appRealm.updateComponent(ldapModel); }); @@ -88,7 +87,7 @@ public class LDAPSyncTest extends AbstractLDAPTest { LDAPTestUtils.addLocalUser(session, appRealm, "marykeycloak", "mary@test.com", "password-app"); - ComponentModel ldapModel = LDAPTestUtils.getLdapProviderModel(session, appRealm); + ComponentModel ldapModel = LDAPTestUtils.getLdapProviderModel(appRealm); LDAPTestUtils.addZipCodeLDAPMapper(appRealm, ldapModel); @@ -139,14 +138,14 @@ public class LDAPSyncTest extends AbstractLDAPTest { // Assert lastSync time updated Assert.assertTrue(ctx.getLdapModel().getLastSync() > 0); - for (UserStorageProviderModel persistentFedModel : testRealm.getUserStorageProviders()) { + testRealm.getUserStorageProvidersStream().forEachOrdered(persistentFedModel -> { if (LDAPStorageProviderFactory.PROVIDER_NAME.equals(persistentFedModel.getProviderId())) { Assert.assertTrue(persistentFedModel.getLastSync() > 0); } else { // Dummy provider has still 0 Assert.assertEquals(0, persistentFedModel.getLastSync()); } - } + }); }); // wait a bit diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/ldap/LDAPTestContext.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/ldap/LDAPTestContext.java index 7f0863317b..e4a806c220 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/ldap/LDAPTestContext.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/ldap/LDAPTestContext.java @@ -35,7 +35,7 @@ public class LDAPTestContext { public static LDAPTestContext init(KeycloakSession session) { RealmModel testRealm = session.realms().getRealm(AbstractLDAPTest.TEST_REALM_NAME); - ComponentModel ldapCompModel = LDAPTestUtils.getLdapProviderModel(session, testRealm); + ComponentModel ldapCompModel = LDAPTestUtils.getLdapProviderModel(testRealm); UserStorageProviderModel ldapModel = new UserStorageProviderModel(ldapCompModel); LDAPStorageProvider ldapProvider = LDAPTestUtils.getLdapProvider(session, ldapModel); return new LDAPTestContext(testRealm, ldapModel, ldapProvider); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/ldap/noimport/LDAPProvidersIntegrationNoImportTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/ldap/noimport/LDAPProvidersIntegrationNoImportTest.java index f317309fa3..0449d10bba 100755 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/ldap/noimport/LDAPProvidersIntegrationNoImportTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/ldap/noimport/LDAPProvidersIntegrationNoImportTest.java @@ -49,7 +49,6 @@ import org.keycloak.testsuite.federation.ldap.LDAPProvidersIntegrationTest; import org.keycloak.testsuite.federation.ldap.LDAPTestAsserts; import org.keycloak.testsuite.federation.ldap.LDAPTestContext; import org.keycloak.testsuite.util.LDAPTestUtils; -import org.keycloak.testsuite.util.WaitUtils; /** @@ -202,7 +201,7 @@ public class LDAPProvidersIntegrationNoImportTest extends LDAPProvidersIntegrati Assert.assertNull(session.users().getUserByUsername("fullname", appRealm)); // Add the user with some fullName into LDAP directly. Ensure that fullName is saved into "cn" attribute in LDAP (currently mapped to model firstName) - ComponentModel ldapModel = LDAPTestUtils.getLdapProviderModel(session, appRealm); + ComponentModel ldapModel = LDAPTestUtils.getLdapProviderModel(appRealm); LDAPStorageProvider ldapFedProvider = LDAPTestUtils.getLdapProvider(session, ldapModel); LDAPTestUtils.addLDAPUser(ldapFedProvider, appRealm, "fullname", "James Dee", "Dee", "fullname@email.org", null, "4578"); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/storage/AbstractUserStorageDirtyDeletionTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/storage/AbstractUserStorageDirtyDeletionTest.java index e1d45a2037..82dc3725da 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/storage/AbstractUserStorageDirtyDeletionTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/storage/AbstractUserStorageDirtyDeletionTest.java @@ -45,8 +45,8 @@ public abstract class AbstractUserStorageDirtyDeletionTest extends AbstractConcu public static void remove20UsersFromStorageProvider(KeycloakSession session) { assertThat(REMOVED_USERS_COUNT, Matchers.lessThan(NUM_USERS)); final RealmModel realm = session.realms().getRealm(TEST_REALM_NAME); - UserStorageManager.getEnabledStorageProviders(session, realm, UserMapStorage.class).stream() - .forEach((UserMapStorage userMapStorage) -> { + UserStorageManager.getEnabledStorageProviders(session, realm, UserMapStorage.class) + .forEachOrdered((UserMapStorage userMapStorage) -> { Set users = new HashSet<>(userMapStorage.getUsernames()); users.stream() .sorted() diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/storage/ClientStorageTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/storage/ClientStorageTest.java index b56d6228bf..49266ecf6e 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/storage/ClientStorageTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/storage/ClientStorageTest.java @@ -284,7 +284,7 @@ public class ClientStorageTest extends AbstractTestRealmKeycloakTest { testingClient.server().run(session -> { RealmModel realm = session.realms().getRealmByName("test"); - ClientStorageProviderModel model = realm.getClientStorageProviders().get(0); + ClientStorageProviderModel model = realm.getClientStorageProvidersStream().findFirst().get(); Calendar eviction = Calendar.getInstance(); eviction.add(Calendar.HOUR, 1); model.setCachePolicy(CacheableStorageProviderModel.CachePolicy.EVICT_DAILY); @@ -307,7 +307,7 @@ public class ClientStorageTest extends AbstractTestRealmKeycloakTest { testingClient.server().run(session -> { RealmModel realm = session.realms().getRealmByName("test"); - ClientStorageProviderModel model = realm.getClientStorageProviders().get(0); + ClientStorageProviderModel model = realm.getClientStorageProvidersStream().findAny().get(); Calendar eviction = Calendar.getInstance(); eviction.add(Calendar.HOUR, 4 * 24); model.setCachePolicy(CacheableStorageProviderModel.CachePolicy.EVICT_WEEKLY); @@ -333,7 +333,7 @@ public class ClientStorageTest extends AbstractTestRealmKeycloakTest { testingClient.server().run(session -> { RealmModel realm = session.realms().getRealmByName("test"); - ClientStorageProviderModel model = realm.getClientStorageProviders().get(0); + ClientStorageProviderModel model = realm.getClientStorageProvidersStream().findFirst().get(); model.setCachePolicy(CacheableStorageProviderModel.CachePolicy.MAX_LIFESPAN); model.setMaxLifespan(1 * 60 * 60 * 1000); realm.updateComponent(model); @@ -381,7 +381,7 @@ public class ClientStorageTest extends AbstractTestRealmKeycloakTest { testingClient.server().run(session -> { RealmModel realm = session.realms().getRealmByName("test"); - ClientStorageProviderModel model = realm.getClientStorageProviders().get(0); + ClientStorageProviderModel model = realm.getClientStorageProvidersStream().findFirst().get(); model.setCachePolicy(CacheableStorageProviderModel.CachePolicy.NO_CACHE); realm.updateComponent(model); }); @@ -401,7 +401,7 @@ public class ClientStorageTest extends AbstractTestRealmKeycloakTest { private void setDefaultCachePolicy() { testingClient.server().run(session -> { RealmModel realm = session.realms().getRealmByName("test"); - ClientStorageProviderModel model = realm.getClientStorageProviders().get(0); + ClientStorageProviderModel model = realm.getClientStorageProvidersStream().findFirst().get(); model.setCachePolicy(CacheableStorageProviderModel.CachePolicy.DEFAULT); realm.updateComponent(model); }); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/storage/UserStorageTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/storage/UserStorageTest.java index 786edb6b8f..68f1dc52ec 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/storage/UserStorageTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/storage/UserStorageTest.java @@ -61,6 +61,7 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.atomic.AtomicReference; +import java.util.stream.Collectors; import static java.util.Calendar.DAY_OF_WEEK; import static java.util.Calendar.HOUR_OF_DAY; @@ -221,7 +222,7 @@ public class UserStorageTest extends AbstractAuthTest { @Test @ModelTest public void testCast(KeycloakSession session) throws Exception { - List list = UserCredentialStoreManager.getCredentialProviders(session, null, CredentialAuthentication.class); + UserCredentialStoreManager.getCredentialProviders(session, CredentialAuthentication.class).collect(Collectors.toList()); } @Test diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/sync/SyncFederationTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/sync/SyncFederationTest.java index 90e41906b3..e2499800b0 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/sync/SyncFederationTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/sync/SyncFederationTest.java @@ -37,6 +37,7 @@ import org.keycloak.timer.TimerProvider; import java.util.HashMap; import java.util.Map; +import java.util.Objects; import java.util.concurrent.TimeUnit; import org.keycloak.testsuite.arquillian.annotation.AuthServerContainerExclude.AuthServer; @@ -137,13 +138,11 @@ public class SyncFederationTest extends AbstractAuthTest { private static final UserStorageProviderModel findDummyProviderModel(RealmModel realm) { - for (ComponentModel component : realm.getComponents()) { - if ("test-sync-dummy".equals(component.getName())) { - return new UserStorageProviderModel(component); - } - } - - return null; + return realm.getComponentsStream() + .filter(component -> Objects.equals(component.getName(), "test-sync-dummy")) + .map(UserStorageProviderModel::new) + .findFirst() + .orElse(null); } /** diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/model/CacheTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/model/CacheTest.java index 7267abd618..6158b9e413 100755 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/model/CacheTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/model/CacheTest.java @@ -28,7 +28,6 @@ import org.keycloak.models.cache.infinispan.ClientAdapter; import org.keycloak.models.cache.infinispan.RealmAdapter; import org.keycloak.testsuite.arquillian.annotation.AuthServerContainerExclude; -import java.util.List; import java.util.Set; import java.util.stream.Collectors; @@ -74,19 +73,15 @@ public class CacheTest extends AbstractTestRealmKeycloakTest { // update realm, then get an AppModel and change it. The AppModel would not be a cache adapter - - // KEYCLOAK-1240 - obtain the realm via session.realms().getRealms() - realm = null; - List realms = session.realms().getRealms(); + realm = session.realms().getRealmsStream().filter(r -> { + assertTrue(r instanceof RealmAdapter); + if ("test".equals(r.getName())) + return true; + return false; + }).findFirst().orElse(null); - for (RealmModel current : realms) { - assertTrue(current instanceof RealmAdapter); - if ("test".equals(current.getName())) { - realm = current; - break; - } - } + assertNotNull(realm); realm.setAccessCodeLifespanLogin(200); testApp = realm.getClientByClientId("test-app"); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/model/ImportTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/model/ImportTest.java index 87f749ae4d..c17c8acc71 100755 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/model/ImportTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/model/ImportTest.java @@ -24,7 +24,6 @@ import org.junit.Test; import org.junit.runners.MethodSorters; import org.keycloak.authorization.AuthorizationProvider; import org.keycloak.authorization.model.ResourceServer; -import org.keycloak.authorization.policy.evaluation.Realm; import org.keycloak.models.ClientModel; import org.keycloak.models.Constants; import org.keycloak.models.KeycloakSession; @@ -39,10 +38,8 @@ import org.keycloak.util.JsonSerialization; import java.io.IOException; import java.nio.charset.StandardCharsets; -import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; -import static org.junit.Assert.assertTrue; import static org.keycloak.testsuite.admin.AbstractAdminTest.loadJson; @@ -68,8 +65,8 @@ public class ImportTest extends AbstractTestRealmKeycloakTest { Assert.assertEquals(600, realm.getAccessCodeLifespanUserAction()); Assert.assertEquals(Constants.DEFAULT_ACCESS_TOKEN_LIFESPAN_FOR_IMPLICIT_FLOW_TIMEOUT, realm.getAccessTokenLifespanForImplicitFlow()); Assert.assertEquals(Constants.DEFAULT_OFFLINE_SESSION_IDLE_TIMEOUT, realm.getOfflineSessionIdleTimeout()); - Assert.assertEquals(1, realm.getRequiredCredentials().size()); - Assert.assertEquals("password", realm.getRequiredCredentials().get(0).getType()); + Assert.assertEquals(1, realm.getRequiredCredentialsStream().count()); + Assert.assertEquals("password", realm.getRequiredCredentialsStream().findFirst().get().getType()); }); } diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/model/OwnerReplacementTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/model/OwnerReplacementTest.java index 319ba5a88a..0543f26472 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/model/OwnerReplacementTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/model/OwnerReplacementTest.java @@ -85,12 +85,7 @@ public class OwnerReplacementTest extends AbstractKeycloakTest { public void componentsTest(KeycloakSession session1) { doTest(session1, // Get ID of some component from realm1 - ((session, realm1) -> { - - List components = realm1.getComponents(); - return components.get(0).getId(); - - }), + ((session, realm1) -> realm1.getComponentsStream().findFirst().get().getId()), // Test lookup realm1 component in realm2 should not work ((session, realm2, realm1ComponentId) -> { @@ -135,12 +130,7 @@ public class OwnerReplacementTest extends AbstractKeycloakTest { public void requiredActionProvidersTest(KeycloakSession session1) { doTest(session1, // Get ID of some object from realm1 - ((session, realm1) -> { - - List reqActions = realm1.getRequiredActionProviders(); - return reqActions.get(0).getId(); - - }), + ((session, realm1) -> realm1.getRequiredActionProvidersStream().findFirst().get().getId()), // Test lookup realm1 object in realm2 should not work ((session, realm2, realm1ReqActionId) -> { @@ -240,8 +230,7 @@ public class OwnerReplacementTest extends AbstractKeycloakTest { ((session, realm1) -> { AuthenticationFlowModel flow = realm1.getFlowByAlias(DefaultAuthenticationFlows.BROWSER_FLOW); - List executions = realm1.getAuthenticationExecutions(flow.getId()); - return executions.get(0).getId(); + return realm1.getAuthenticationExecutionsStream(flow.getId()).findFirst().get().getId(); }), // Test lookup realm1 object in realm2 should not work @@ -289,12 +278,7 @@ public class OwnerReplacementTest extends AbstractKeycloakTest { public void authenticationConfigsTest(KeycloakSession session1) { doTest(session1, // Get ID of some object from realm1 - ((session, realm1) -> { - - List configs = realm1.getAuthenticatorConfigs(); - return configs.get(0).getId(); - - }), + ((session, realm1) -> realm1.getAuthenticatorConfigsStream().findFirst().get().getId()), // Test lookup realm1 object in realm2 should not work ((session, realm2, realm1AuthConfigId) -> { diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/FlowUtil.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/FlowUtil.java index d8c0d4a6fe..b97422c631 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/FlowUtil.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/FlowUtil.java @@ -11,12 +11,12 @@ import org.keycloak.models.RealmModel; import org.keycloak.models.utils.DefaultAuthenticationFlows; import org.keycloak.services.resources.admin.AuthenticationManagementResource; -import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Random; import java.util.UUID; import java.util.function.Consumer; +import java.util.stream.Collectors; public class FlowUtil { private RealmModel realm; @@ -115,13 +115,7 @@ public class FlowUtil { } public FlowUtil clear() { - // Get executions from current flow - List executions = realm.getAuthenticationExecutions(currentFlow.getId()); - // Remove all executions - for (AuthenticationExecutionModel authExecution : executions) { - realm.removeAuthenticatorExecution(authExecution); - } - + realm.getAuthenticationExecutionsStream(currentFlow.getId()).forEachOrdered(realm::removeAuthenticatorExecution); return this; } @@ -244,11 +238,7 @@ public class FlowUtil { private List getExecutions() { if (executions == null) { - List execs = realm.getAuthenticationExecutions(currentFlow.getId()); - if (execs == null) { - throw new FlowUtilException("Can't get executions of unknown flow " + currentFlow.getId()); - } - executions = new ArrayList<>(execs); + executions = realm.getAuthenticationExecutionsStream(currentFlow.getId()).collect(Collectors.toList()); } return executions; } diff --git a/testsuite/utils/src/main/java/org/keycloak/testsuite/util/cli/LdapManyGroupsInitializerCommand.java b/testsuite/utils/src/main/java/org/keycloak/testsuite/util/cli/LdapManyGroupsInitializerCommand.java index 26c778c368..4e7231588d 100644 --- a/testsuite/utils/src/main/java/org/keycloak/testsuite/util/cli/LdapManyGroupsInitializerCommand.java +++ b/testsuite/utils/src/main/java/org/keycloak/testsuite/util/cli/LdapManyGroupsInitializerCommand.java @@ -17,12 +17,8 @@ package org.keycloak.testsuite.util.cli; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; +import java.util.*; +import java.util.stream.Collectors; import org.keycloak.component.ComponentModel; import org.keycloak.models.KeycloakSession; @@ -66,7 +62,8 @@ public class LdapManyGroupsInitializerCommand extends AbstractCommand { int subgroupsInEveryGroup = getIntArg(4); RealmModel realm = session.realms().getRealmByName(realmName); - List components = realm.getComponents(realm.getId(), UserStorageProvider.class.getName()); + List components = realm.getComponentsStream(realm.getId(), UserStorageProvider.class.getName()) + .collect(Collectors.toList()); if (components.size() != 1) { log.errorf("Expected 1 LDAP Provider, but found: %d providers", components.size()); throw new HandledException(); @@ -107,16 +104,15 @@ public class LdapManyGroupsInitializerCommand extends AbstractCommand { private ComponentModel getMapperModel(RealmModel realm, ComponentModel ldapModel, String mapperName) { - List ldapMappers = realm.getComponents(ldapModel.getId(), LDAPStorageMapper.class.getName()); - Optional optional = ldapMappers.stream().filter((ComponentModel mapper) -> { - return mapper.getName().equals(mapperName); - }).findFirst(); + Optional first = realm.getComponentsStream(ldapModel.getId(), LDAPStorageMapper.class.getName()) + .filter(component -> Objects.equals(component.getName(), mapperName)) + .findFirst(); - if (!optional.isPresent()) { + if (first.isPresent()) { + return first.get(); + } else { log.errorf("Not present LDAP mapper called '%s'", mapperName); - throw new HandledException(); + throw new RuntimeException(); } - - return optional.get(); } } diff --git a/testsuite/utils/src/main/java/org/keycloak/testsuite/util/cli/LdapManyObjectsInitializerCommand.java b/testsuite/utils/src/main/java/org/keycloak/testsuite/util/cli/LdapManyObjectsInitializerCommand.java index b35973912c..fdf246c015 100644 --- a/testsuite/utils/src/main/java/org/keycloak/testsuite/util/cli/LdapManyObjectsInitializerCommand.java +++ b/testsuite/utils/src/main/java/org/keycloak/testsuite/util/cli/LdapManyObjectsInitializerCommand.java @@ -17,14 +17,8 @@ package org.keycloak.testsuite.util.cli; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; +import java.util.*; +import java.util.stream.Collectors; import org.keycloak.component.ComponentModel; import org.keycloak.models.KeycloakSession; @@ -73,7 +67,8 @@ public class LdapManyObjectsInitializerCommand extends AbstractCommand { int countGroups = getIntArg(5); RealmModel realm = session.realms().getRealmByName(realmName); - List components = realm.getComponents(realm.getId(), UserStorageProvider.class.getName()); + List components = realm.getComponentsStream(realm.getId(), UserStorageProvider.class.getName()) + .collect(Collectors.toList()); if (components.size() != 1) { log.errorf("Expected 1 LDAP Provider, but found: %d providers", components.size()); throw new HandledException(); @@ -130,17 +125,16 @@ public class LdapManyObjectsInitializerCommand extends AbstractCommand { private ComponentModel getMapperModel(RealmModel realm, ComponentModel ldapModel, String mapperName) { - List ldapMappers = realm.getComponents(ldapModel.getId(), LDAPStorageMapper.class.getName()); - Optional optional = ldapMappers.stream().filter((ComponentModel mapper) -> { - return mapper.getName().equals(mapperName); - }).findFirst(); + Optional first = realm.getComponentsStream(ldapModel.getId(), LDAPStorageMapper.class.getName()) + .filter(component -> Objects.equals(component.getName(), mapperName)) + .findFirst(); - if (!optional.isPresent()) { + if (first.isPresent()) { + return first.get(); + } else { log.errorf("Not present LDAP mapper called '%s'", mapperName); - throw new HandledException(); + throw new RuntimeException(); } - - return optional.get(); } 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 d48fe0f4f6..644adc8d28 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 @@ -45,9 +45,7 @@ public class TestCacheUtils { realm.getTopLevelGroupsStream().forEach(group -> cacheGroupRecursive(realm, group)); - for (ClientScopeModel clientScope : realm.getClientScopes()) { - realm.getClientScopeById(clientScope.getId()); - } + realm.getClientScopesStream().map(ClientScopeModel::getId).forEach(realm::getClientScopeById); for (UserModel user : session.users().getUsers(realm)) { session.users().getUserById(user.getId(), realm);