KEYCLOAK-14901 Replace deprecated ClientProvider related methods across Keycloak

This commit is contained in:
Martin Kanis 2020-07-29 15:07:52 +02:00 committed by Hynek Mlnařík
parent 76f7fbb984
commit 4e9bdd44f3
52 changed files with 419 additions and 489 deletions

View file

@ -140,6 +140,7 @@ public class RolePolicyProviderFactory implements PolicyProviderFactory<RolePoli
}
private void updateRoles(Policy policy, AuthorizationProvider authorization, Set<RolePolicyRepresentation.RoleDefinition> roles) {
KeycloakSession session = authorization.getKeycloakSession();
RealmModel realm = authorization.getRealm();
Set<RolePolicyRepresentation.RoleDefinition> updatedRoles = new HashSet<>();
@ -175,7 +176,7 @@ public class RolePolicyProviderFactory implements PolicyProviderFactory<RolePoli
// fallback to find any client role with the given name
if (role == null) {
String finalRoleName = roleName;
role = realm.getClients().stream().map(clientModel -> clientModel.getRole(finalRoleName)).filter(roleModel -> roleModel != null)
role = realm.getClientsStream().map(clientModel -> clientModel.getRole(finalRoleName)).filter(roleModel -> roleModel != null)
.findFirst().orElse(null);
}
@ -215,7 +216,8 @@ public class RolePolicyProviderFactory implements PolicyProviderFactory<RolePoli
if (container instanceof RealmModel) {
RealmModel realm = (RealmModel) container;
realm.getClients().forEach(clientModel -> updateResourceServer(clientModel, removedRole, resourceServerStore, policyStore));
realm.getClientsStream()
.forEach(clientModel -> updateResourceServer(clientModel, removedRole, resourceServerStore, policyStore));
} else {
ClientModel clientModel = (ClientModel) container;
updateResourceServer(clientModel, removedRole, resourceServerStore, policyStore);

View file

@ -182,7 +182,7 @@ public class UserPolicyProviderFactory implements PolicyProviderFactory<UserPoli
UserModel removedUser = ((UserRemovedEvent) event).getUser();
RealmModel realm = ((UserRemovedEvent) event).getRealm();
ResourceServerStore resourceServerStore = storeFactory.getResourceServerStore();
realm.getClients().forEach(clientModel -> {
realm.getClientsStream().forEach(clientModel -> {
ResourceServer resourceServer = resourceServerStore.findById(clientModel.getId());
if (resourceServer != null) {

View file

@ -38,6 +38,7 @@ import org.keycloak.storage.ldap.mappers.AbstractLDAPStorageMapper;
import org.keycloak.storage.ldap.mappers.membership.CommonLDAPGroupMapper;
import org.keycloak.storage.ldap.mappers.membership.CommonLDAPGroupMapperConfig;
import org.keycloak.storage.ldap.mappers.membership.LDAPGroupMapperMode;
import org.keycloak.storage.ldap.mappers.membership.MembershipType;
import org.keycloak.storage.ldap.mappers.membership.UserRolesRetrieveStrategy;
import org.keycloak.storage.user.SynchronizationResult;
@ -46,7 +47,8 @@ import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.keycloak.storage.ldap.mappers.membership.MembershipType;
import java.util.function.Consumer;
import java.util.stream.Stream;
/**
* Map realm roles or roles of particular client to LDAP groups
@ -178,10 +180,9 @@ public class RoleLDAPStorageMapper extends AbstractLDAPStorageMapper implements
RoleContainerModel roleContainer = getTargetRoleContainer(realm);
Set<RoleModel> keycloakRoles = roleContainer.getRoles();
Stream<RoleModel> keycloakRoles = roleContainer.getRolesStream();
for (RoleModel keycloakRole : keycloakRoles) {
String roleName = keycloakRole.getName();
Consumer<String> syncRoleFromKCToLDAP = roleName -> {
if (ldapRoleNames.contains(roleName)) {
syncResult.increaseUpdated();
} else {
@ -189,7 +190,8 @@ public class RoleLDAPStorageMapper extends AbstractLDAPStorageMapper implements
createLDAPRole(roleName);
syncResult.increaseAdded();
}
}
};
keycloakRoles.map(RoleModel::getName).forEach(syncRoleFromKCToLDAP);
return syncResult;
}

View file

@ -31,6 +31,7 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Stream;
@ -661,19 +662,9 @@ public class ClientAdapter implements ClientModel, CachedObject {
if (isUpdated()) return updated.hasScope(role);
if (cached.isFullScopeAllowed() || cached.getScope().contains(role.getId())) return true;
Set<RoleModel> roles = getScopeMappings();
if (getScopeMappingsStream().anyMatch(r -> r.hasRole(role))) return true;
for (RoleModel mapping : roles) {
if (mapping.hasRole(role)) return true;
}
roles = getRoles();
if (roles.contains(role)) return true;
for (RoleModel mapping : roles) {
if (mapping.hasRole(role)) return true;
}
return false;
return getRolesStream().anyMatch(r -> (Objects.equals(r, role) || r.hasRole(role)));
}
@Override

View file

@ -583,9 +583,9 @@ public class RealmCacheSession implements CacheRealmProvider {
invalidationEvents.add(ClientRemovedEvent.create(client));
cache.clientRemoval(realm.getId(), id, client.getClientId(), invalidations);
for (RoleModel role : client.getRoles()) {
client.getRolesStream().forEach(role -> {
roleRemovalInvalidations(role.getId(), role.getName(), client.getId());
}
});
if (client.isServiceAccountsEnabled()) {
UserModel serviceAccount = session.users().getServiceAccount(client);

View file

@ -17,7 +17,6 @@
package org.keycloak.models.cache.infinispan.events;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
@ -29,6 +28,8 @@ import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
import org.infinispan.commons.marshall.Externalizer;
import org.infinispan.commons.marshall.MarshallUtil;
import org.infinispan.commons.marshall.SerializeWith;
@ -51,10 +52,7 @@ public class ClientRemovedEvent extends InvalidationEvent implements RealmCacheI
event.realmId = client.getRealm().getId();
event.clientUuid = client.getId();
event.clientId = client.getClientId();
event.clientRoles = new HashMap<>();
for (RoleModel clientRole : client.getRoles()) {
event.clientRoles.put(clientRole.getId(), clientRole.getName());
}
event.clientRoles = client.getRolesStream().collect(Collectors.toMap(RoleModel::getId, RoleModel::getName));
return event;
}

View file

@ -46,6 +46,7 @@ import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Stream;
/**
@ -688,19 +689,14 @@ public class ClientAdapter implements ClientModel, JpaModel<ClientEntity> {
@Override
public boolean hasScope(RoleModel role) {
if (isFullScopeAllowed()) return true;
Set<RoleModel> roles = getScopeMappings();
if (roles.contains(role)) return true;
for (RoleModel mapping : roles) {
if (mapping.hasRole(role)) return true;
}
roles = getRoles();
if (roles.contains(role)) return true;
Predicate<RoleModel> hasRoleOrEquals = r -> (Objects.equals(r, role) || r.hasRole(role));
for (RoleModel mapping : roles) {
if (mapping.hasRole(role)) return true;
if (getScopeMappingsStream().anyMatch(hasRoleOrEquals)) {
return true;
}
return false;
return getRolesStream().anyMatch(hasRoleOrEquals);
}
@Override

View file

@ -26,9 +26,6 @@ import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
import com.google.common.base.Functions;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@ -454,10 +451,7 @@ public abstract class MapClientAdapter extends AbstractClientModel<MapClientEnti
return true;
}
Set<RoleModel> roles = getRoles();
if (roles.contains(role)) return true;
return roles.stream().anyMatch(r -> r.hasRole(role));
return getRolesStream().anyMatch(r -> (Objects.equals(r, role) || r.hasRole(role)));
}
/*************** Default roles ****************/

View file

@ -25,8 +25,6 @@ import org.keycloak.models.ModelDuplicateException;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RealmModel.ClientUpdatedEvent;
import org.keycloak.models.RealmProvider;
import org.keycloak.models.RoleModel;
import org.keycloak.models.map.storage.MapKeycloakTransaction;
import org.keycloak.models.map.common.Serialization;
import java.util.Comparator;
@ -41,7 +39,6 @@ import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.keycloak.models.map.storage.MapStorage;
import static org.keycloak.common.util.StackUtil.getShortStackTrace;
import org.keycloak.models.RoleProvider;
public class MapClientProvider implements ClientProvider {

View file

@ -35,7 +35,7 @@ public class RealmSynchronizer implements Synchronizer<RealmRemovedEvent> {
AuthorizationProvider authorizationProvider = providerFactory.create(event.getKeycloakSession());
StoreFactory storeFactory = authorizationProvider.getStoreFactory();
event.getRealm().getClients().forEach(clientModel -> {
event.getRealm().getClientsStream().forEach(clientModel -> {
ResourceServer resourceServer = storeFactory.getResourceServerStore().findById(clientModel.getId());
if (resourceServer != null) {

View file

@ -89,7 +89,7 @@ public class UserSynchronizer implements Synchronizer<UserRemovedEvent> {
RealmModel realm = event.getRealm();
UserModel userModel = event.getUser();
realm.getClients().forEach(clientModel -> {
realm.getClientsStream().forEach(clientModel -> {
ResourceServer resourceServer = resourceServerStore.findById(clientModel.getId());
if (resourceServer != null) {

View file

@ -19,12 +19,10 @@ package org.keycloak.migration.migrators;
import org.keycloak.migration.ModelVersion;
import org.keycloak.models.AuthenticationFlowModel;
import org.keycloak.models.ClientModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.OTPPolicy;
import org.keycloak.models.RealmModel;
import org.keycloak.models.utils.DefaultAuthenticationFlows;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.representations.idm.RealmRepresentation;
import java.util.List;
@ -43,17 +41,17 @@ public class MigrateTo1_5_0 implements Migration {
public void migrate(KeycloakSession session) {
List<RealmModel> realms = session.realms().getRealms();
for (RealmModel realm : realms) {
migrateRealm(realm);
migrateRealm(session, realm);
}
}
@Override
public void migrateImport(KeycloakSession session, RealmModel realm, RealmRepresentation rep, boolean skipUserDependent) {
migrateRealm(realm);
migrateRealm(session, realm);
}
protected void migrateRealm(RealmModel realm) {
protected void migrateRealm(KeycloakSession session, RealmModel realm) {
DefaultAuthenticationFlows.migrateFlows(realm); // add reset credentials flo
realm.setOTPPolicy(OTPPolicy.DEFAULT_POLICY);
realm.setBrowserFlow(realm.getFlowByAlias(DefaultAuthenticationFlows.BROWSER_FLOW));
@ -74,8 +72,6 @@ public class MigrateTo1_5_0 implements Migration {
realm.setClientAuthenticationFlow(clientAuthFlow);
}
for (ClientModel client : realm.getClients()) {
client.setClientAuthenticatorType(KeycloakModelUtils.getDefaultClientAuthenticatorType());
}
realm.getClientsStream().forEach(MigrationUtils::setDefaultClientAuthenticatorType);
}
}

View file

@ -74,7 +74,7 @@ public class MigrateTo2_1_0 implements Migration {
AuthorizationProvider authorizationProvider = session.getProvider(AuthorizationProvider.class);
StoreFactory storeFactory = authorizationProvider.getStoreFactory();
PolicyStore policyStore = storeFactory.getPolicyStore();
realm.getClients().forEach(clientModel -> {
realm.getClientsStream().forEach(clientModel -> {
ResourceServer resourceServer = storeFactory.getResourceServerStore().findById(clientModel.getId());
if (resourceServer != null) {

View file

@ -19,7 +19,6 @@ package org.keycloak.migration.migrators;
import org.keycloak.migration.ModelVersion;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientScopeModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
@ -40,9 +39,7 @@ public class MigrateTo2_3_0 implements Migration {
}
protected void migrateRealm(RealmModel realm) {
for (ClientModel client : realm.getClients()) {
MigrationUtils.updateProtocolMappers(client);
}
realm.getClientsStream().forEach(MigrationUtils::updateProtocolMappers);
for (ClientScopeModel clientScope : realm.getClientScopes()) {
MigrationUtils.updateProtocolMappers(clientScope);

View file

@ -55,7 +55,7 @@ public class MigrateTo3_0_0 implements Migration {
}
protected void migrateRealm(RealmModel realm) {
realm.getClients().stream()
realm.getClientsStream()
.filter(clientModel -> defaultClients.contains(clientModel.getId()))
.filter(clientModel -> Objects.isNull(clientModel.getProtocol()))
.forEach(clientModel -> clientModel.setProtocol("openid-connect"));

View file

@ -94,7 +94,7 @@ public class MigrateTo4_0_0 implements Migration {
// If client has scope for offline_access role (either directly or through fullScopeAllowed), then add offline_access client
// scope as optional scope to the client. If it's indirectly (no fullScopeAllowed), then remove role from the scoped roles
RoleModel offlineAccessRole = realm.getRole(OAuth2Constants.OFFLINE_ACCESS);
ClientScopeModel offlineAccessScope = null;
ClientScopeModel offlineAccessScope;
if (offlineAccessRole == null) {
LOG.infof("Role 'offline_access' not available in realm '%s'. Skip migration of offline_access client scope.", realm.getName());
} else {
@ -102,32 +102,32 @@ public class MigrateTo4_0_0 implements Migration {
if (offlineAccessScope == null) {
LOG.infof("Client scope 'offline_access' not available in realm '%s'. Skip migration of offline_access client scope.", realm.getName());
} else {
for (ClientModel client : realm.getClients()) {
if ("openid-connect".equals(client.getProtocol())
&& !client.isBearerOnly()
&& client.hasScope(offlineAccessRole)
&& !client.getClientScopes(false, true).containsKey(OAuth2Constants.OFFLINE_ACCESS)) {
LOG.debugf("Adding client scope 'offline_access' as optional scope to client '%s' in realm '%s'.", client.getClientId(), realm.getName());
client.addClientScope(offlineAccessScope, false);
if (!client.isFullScopeAllowed()) {
LOG.debugf("Removing role scope mapping for role 'offline_access' from client '%s' in realm '%s'.", client.getClientId(), realm.getName());
client.deleteScopeMapping(offlineAccessRole);
}
}
}
realm.getClientsStream()
.filter(MigrationUtils::isOIDCNonBearerOnlyClient)
.filter(c -> c.hasScope(offlineAccessRole))
.filter(c -> !c.getClientScopes(false, true).containsKey(OAuth2Constants.OFFLINE_ACCESS))
.peek(c -> {
LOG.debugf("Adding client scope 'offline_access' as optional scope to client '%s' in realm '%s'.", c.getClientId(), realm.getName());
c.addClientScope(offlineAccessScope, false);
})
.filter(c -> !c.isFullScopeAllowed())
.forEach(c -> {
LOG.debugf("Removing role scope mapping for role 'offline_access' from client '%s' in realm '%s'.", c.getClientId(), realm.getName());
c.deleteScopeMapping(offlineAccessRole);
});
}
}
// Clients with consentRequired, which don't have any client scopes will be added itself to require consent, so that consent screen is shown when users authenticate
for (ClientModel client : realm.getClients()) {
if (client.isConsentRequired() && client.getClientScopes(true, true).isEmpty()) {
LOG.debugf("Adding client '%s' of realm '%s' to display itself on consent screen", client.getClientId(), realm.getName());
client.setDisplayOnConsentScreen(true);
String consentText = client.getName()==null ? client.getClientId() : client.getName();
client.setConsentScreenText(consentText);
}
}
realm.getClientsStream()
.filter(ClientModel::isConsentRequired)
.filter(c -> c.getClientScopes(true, true).isEmpty())
.forEach(c -> {
LOG.debugf("Adding client '%s' of realm '%s' to display itself on consent screen", c.getClientId(), realm.getName());
c.setDisplayOnConsentScreen(true);
String consentText = c.getName() == null ? c.getClientId() : c.getName();
c.setConsentScreenText(consentText);
});
}
}

View file

@ -20,7 +20,6 @@ package org.keycloak.migration.migrators;
import org.jboss.logging.Logger;
import org.keycloak.migration.MigrationProvider;
import org.keycloak.migration.ModelVersion;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientScopeModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
@ -63,12 +62,12 @@ public class MigrateTo4_6_0 implements Migration {
LOG.debugf("Added '%s' and '%s' default client scopes", rolesScope.getName(), webOriginsScope.getName());
// Assign "roles" and "web-origins" clientScopes to all the OIDC clients
for (ClientModel client : realm.getClients()) {
if ((client.getProtocol()==null || "openid-connect".equals(client.getProtocol())) && (!client.isBearerOnly())) {
client.addClientScope(rolesScope, true);
client.addClientScope(webOriginsScope, true);
}
}
realm.getClientsStream()
.filter(MigrationUtils::isOIDCNonBearerOnlyClient)
.forEach(c -> {
c.addClientScope(rolesScope, true);
c.addClientScope(webOriginsScope, true);
});
LOG.debugf("Client scope '%s' assigned to all the clients", rolesScope.getName());
}

View file

@ -20,7 +20,6 @@ package org.keycloak.migration.migrators;
import org.jboss.logging.Logger;
import org.keycloak.migration.MigrationProvider;
import org.keycloak.migration.ModelVersion;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientScopeModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
@ -63,11 +62,9 @@ public class MigrateTo6_0_0 implements Migration {
LOG.debugf("Added '%s' optional client scope", mpJWTScope.getName());
// assign 'microprofile-jwt' optional client scope to all the OIDC clients.
for (ClientModel client : realm.getClients()) {
if ((client.getProtocol() == null || "openid-connect".equals(client.getProtocol())) && (!client.isBearerOnly())) {
client.addClientScope(mpJWTScope, false);
}
}
realm.getClientsStream()
.filter(MigrationUtils::isOIDCNonBearerOnlyClient)
.forEach(c -> c.addClientScope(mpJWTScope, false));
LOG.debugf("Client scope '%s' assigned to all the clients", mpJWTScope.getName());
}

View file

@ -107,4 +107,11 @@ public class MigrationUtils {
}
}
public static void setDefaultClientAuthenticatorType(ClientModel s) {
s.setClientAuthenticatorType(KeycloakModelUtils.getDefaultClientAuthenticatorType());
}
public static boolean isOIDCNonBearerOnlyClient(ClientModel c) {
return (c.getProtocol() == null || "openid-connect".equals(c.getProtocol())) && !c.isBearerOnly();
}
}

View file

@ -586,13 +586,10 @@ public final class KeycloakModelUtils {
}
public static boolean isClientScopeUsed(RealmModel realm, ClientScopeModel clientScope) {
for (ClientModel client : realm.getClients()) {
if ((client.getClientScopes(true, false).containsKey(clientScope.getName())) ||
(client.getClientScopes(false, false).containsKey(clientScope.getName()))) {
return true;
}
}
return false;
return realm.getClientsStream()
.filter(c -> (c.getClientScopes(true, false).containsKey(clientScope.getName())) ||
(c.getClientScopes(false, false).containsKey(clientScope.getName())))
.findFirst().isPresent();
}
public static ClientScopeModel getClientScopeByName(RealmModel realm, String clientScopeName) {
@ -602,14 +599,7 @@ public final class KeycloakModelUtils {
}
}
// check if we are referencing a client instead of a scope
if (realm.getClients() != null) {
for (ClientModel client : realm.getClients()) {
if (clientScopeName.equals(client.getClientId())) {
return client;
}
}
}
return null;
return realm.getClientsStream().filter(c -> clientScopeName.equals(c.getClientId())).findFirst().orElse(null);
}
/**

View file

@ -25,11 +25,10 @@ import org.keycloak.models.RealmModel;
import org.keycloak.provider.ProviderEvent;
import org.keycloak.provider.ProviderEventListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@ -62,7 +61,7 @@ public abstract class AbstractLoginProtocolFactory implements LoginProtocolFacto
// Create default client scopes for realm built-in clients too
if (addScopesToExistingClients) {
addDefaultClientScopes(newRealm, newRealm.getClients());
addDefaultClientScopes(newRealm, newRealm.getClientsStream());
}
}
@ -73,27 +72,27 @@ public abstract class AbstractLoginProtocolFactory implements LoginProtocolFacto
protected void addDefaultClientScopes(RealmModel realm, ClientModel newClient) {
addDefaultClientScopes(realm, Arrays.asList(newClient));
addDefaultClientScopes(realm, Stream.of(newClient));
}
protected void addDefaultClientScopes(RealmModel realm, List<ClientModel> newClients) {
protected void addDefaultClientScopes(RealmModel realm, Stream<ClientModel> newClients) {
Set<ClientScopeModel> defaultClientScopes = realm.getDefaultClientScopes(true).stream()
.filter(clientScope -> getId().equals(clientScope.getProtocol()))
.collect(Collectors.toSet());
if (!defaultClientScopes.isEmpty()) {
for (ClientModel newClient : newClients) {
newClient.addClientScopes(defaultClientScopes, true);
}
}
Set<ClientScopeModel> nonDefaultClientScopes = realm.getDefaultClientScopes(false).stream()
.filter(clientScope -> getId().equals(clientScope.getProtocol()))
.collect(Collectors.toSet());
if (!nonDefaultClientScopes.isEmpty()) {
for (ClientModel newClient : newClients) {
newClient.addClientScopes(nonDefaultClientScopes, false);
}
}
Consumer<ClientModel> addDefault = c -> c.addClientScopes(defaultClientScopes, true);
Consumer<ClientModel> addNonDefault = c -> c.addClientScopes(nonDefaultClientScopes, false);
if (!defaultClientScopes.isEmpty() && !nonDefaultClientScopes.isEmpty())
newClients.forEach(addDefault.andThen(addNonDefault));
else if (!defaultClientScopes.isEmpty())
newClients.forEach(addDefault);
else if (!nonDefaultClientScopes.isEmpty())
newClients.forEach(addNonDefault);
}
protected abstract void addDefaults(ClientModel realm);

View file

@ -49,7 +49,6 @@ public interface RoleContainerModel {
boolean removeRole(RoleModel role);
// TODO switch all usages to the stream variant
@Deprecated
default Set<RoleModel> getRoles() {
return getRolesStream().collect(Collectors.toSet());
@ -57,7 +56,6 @@ public interface RoleContainerModel {
Stream<RoleModel> getRolesStream();
// TODO switch all usages to the stream variant
@Deprecated
default Set<RoleModel> getRoles(Integer firstResult, Integer maxResults) {
return getRolesStream(firstResult, maxResults).collect(Collectors.toSet());
@ -65,7 +63,6 @@ public interface RoleContainerModel {
Stream<RoleModel> getRolesStream(Integer firstResult, Integer maxResults);
// TODO switch all usages to the stream variant
@Deprecated
default Set<RoleModel> searchForRoles(String search, Integer first, Integer max) {
return searchForRolesStream(search, first, max).collect(Collectors.toSet());

View file

@ -22,7 +22,11 @@ import org.keycloak.models.RoleModel;
import org.keycloak.models.UserModel;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@ -35,13 +39,10 @@ public class DefaultRoles {
set.add(realm.getRole(r));
}
for (ClientModel application : realm.getClients()) {
for (String r : application.getDefaultRoles()) {
set.add(application.getRole(r));
}
}
return set;
Function<ClientModel, Set<RoleModel>> defaultRoles = i -> i.getDefaultRoles().stream().map(i::getRole).collect(Collectors.toSet());
realm.getClientsStream().map(defaultRoles).forEach(set::addAll);
return set;
}
public static void addDefaultRoles(RealmModel realm, UserModel userModel) {
for (RoleModel role : getDefaultRoles(realm)) {

View file

@ -189,6 +189,16 @@ public class RoleUtils {
.collect(Collectors.toSet());
}
/**
* @param roles
* @return stream with composite roles expanded
*/
public static Stream<RoleModel> expandCompositeRolesStream(Stream<RoleModel> roles) {
Set<RoleModel> visited = new HashSet<>();
return roles.flatMap(roleModel -> RoleUtils.expandCompositeRolesStream(roleModel, visited));
}
/**
* @param user

View file

@ -31,6 +31,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.keycloak.authorization.AuthorizationProvider;
import org.keycloak.authorization.AuthorizationProviderFactory;
@ -120,7 +121,7 @@ public class ExportUtils {
List<ClientModel> clients = Collections.emptyList();
if (options.isClientsIncluded()) {
clients = realm.getClients();
clients = realm.getClientsStream().collect(Collectors.toList());
List<ClientRepresentation> clientReps = new ArrayList<>();
for (ClientModel app : clients) {
ClientRepresentation clientRep = exportClient(session, app);
@ -133,22 +134,18 @@ public class ExportUtils {
if (options.isGroupsAndRolesIncluded()) {
ModelToRepresentation.exportGroups(realm, rep);
List<RoleRepresentation> realmRoleReps = null;
Map<String, List<RoleRepresentation>> clientRolesReps = new HashMap<>();
Set<RoleModel> realmRoles = realm.getRoles();
if (realmRoles != null && realmRoles.size() > 0) {
realmRoleReps = exportRoles(realmRoles);
}
List<RoleRepresentation> realmRoleReps = exportRoles(realm.getRolesStream());
RolesRepresentation rolesRep = new RolesRepresentation();
if (realmRoleReps != null) {
if (!realmRoleReps.isEmpty()) {
rolesRep.setRealm(realmRoleReps);
}
if (options.isClientsIncluded()) {
for (ClientModel client : clients) {
Set<RoleModel> currentAppRoles = client.getRoles();
Stream<RoleModel> currentAppRoles = client.getRolesStream();
List<RoleRepresentation> currentAppRoleReps = exportRoles(currentAppRoles);
clientRolesReps.put(client.getClientId(), currentAppRoleReps);
}
@ -411,14 +408,8 @@ public class ExportUtils {
}
}
public static List<RoleRepresentation> exportRoles(Collection<RoleModel> roles) {
List<RoleRepresentation> roleReps = new ArrayList<RoleRepresentation>();
for (RoleModel role : roles) {
RoleRepresentation roleRep = exportRole(role);
roleReps.add(roleRep);
}
return roleReps;
public static List<RoleRepresentation> exportRoles(Stream<RoleModel> roles) {
return roles.map(ExportUtils::exportRole).collect(Collectors.toList());
}
public static List<String> getRoleNames(Collection<RoleModel> roles) {

View file

@ -38,6 +38,7 @@ import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;
/**
@ -102,14 +103,8 @@ public class ApplicationsBean {
private Set<ClientModel> getApplications(KeycloakSession session, RealmModel realm, UserModel user) {
Set<ClientModel> clients = new HashSet<>();
for (ClientModel client : realm.getClients()) {
// Don't show bearerOnly clients
if (client.isBearerOnly()) {
continue;
}
clients.add(client);
}
Predicate<ClientModel> bearerOnly = ClientModel::isBearerOnly;
clients.addAll(realm.getClientsStream().filter(bearerOnly.negate()).collect(Collectors.toSet()));
List<UserConsentModel> consents = session.users().getConsents(realm, user.getId());

View file

@ -30,6 +30,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;
/**
@ -68,11 +69,7 @@ public class ClientRolesPartialImport {
ClientModel client = realm.getClientByClientId(clientId);
if (client == null) return false;
for (RoleModel role : client.getRoles()) {
if (getName(roleRep).equals(role.getName())) return true;
}
return false;
return client.getRolesStream().anyMatch(role -> Objects.equals(getName(roleRep), role.getName()));
}
// check if client currently exists or will exists as a result of this partial import

View file

@ -24,6 +24,7 @@ import org.keycloak.representations.idm.RoleRepresentation;
import org.keycloak.services.resources.admin.RoleResource;
import java.util.List;
import java.util.Objects;
import java.util.Set;
/**
@ -56,20 +57,15 @@ public class RealmRolesPartialImport extends AbstractPartialImport<RoleRepresent
@Override
public String getModelId(RealmModel realm, KeycloakSession session, RoleRepresentation roleRep) {
for (RoleModel role : realm.getRoles()) {
if (getName(roleRep).equals(role.getName())) return role.getId();
}
return null;
return realm.getRolesStream()
.filter(r -> Objects.equals(getName(roleRep), r.getName()))
.map(RoleModel::getId)
.findFirst().orElse(null);
}
@Override
public boolean exists(RealmModel realm, KeycloakSession session, RoleRepresentation roleRep) {
for (RoleModel role : realm.getRoles()) {
if (getName(roleRep).equals(role.getName())) return true;
}
return false;
return realm.getRolesStream().anyMatch(role -> Objects.equals(getName(roleRep), role.getName()));
}
@Override

View file

@ -21,7 +21,6 @@ import org.jboss.logging.Logger;
import org.jboss.resteasy.spi.HttpRequest;
import org.keycloak.OAuth2Constants;
import org.keycloak.OAuthErrorException;
import org.keycloak.Token;
import org.keycloak.TokenCategory;
import org.keycloak.TokenVerifier;
import org.keycloak.broker.oidc.OIDCIdentityProvider;
@ -61,7 +60,6 @@ import org.keycloak.protocol.ProtocolMapperUtils;
import org.keycloak.protocol.oidc.mappers.OIDCAccessTokenMapper;
import org.keycloak.protocol.oidc.mappers.OIDCIDTokenMapper;
import org.keycloak.protocol.oidc.mappers.UserInfoTokenMapper;
import org.keycloak.protocol.oidc.utils.OAuth2Code;
import org.keycloak.protocol.oidc.utils.OIDCResponseType;
import org.keycloak.representations.AccessToken;
import org.keycloak.representations.AccessTokenResponse;
@ -83,16 +81,15 @@ import org.keycloak.util.TokenUtil;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
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.stream.Collectors;
import java.util.stream.Stream;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
@ -495,21 +492,21 @@ public class TokenManager {
} else {
// 1 - Client roles of this client itself
Set<RoleModel> scopeMappings = new HashSet<>(client.getRoles());
Stream<RoleModel> scopeMappings = client.getRolesStream();
// 2 - Role mappings of client itself + default client scopes + optional client scopes requested by scope parameter (if applyScopeParam is true)
for (ClientScopeModel clientScope : clientScopes) {
if (logger.isTraceEnabled()) {
logger.tracef("Adding client scope role mappings of client scope '%s' to client '%s'", clientScope.getName(), client.getClientId());
}
scopeMappings.addAll(clientScope.getScopeMappings());
scopeMappings = Stream.concat(scopeMappings, clientScope.getScopeMappingsStream());
}
// 3 - Expand scope mappings
scopeMappings = RoleUtils.expandCompositeRoles(scopeMappings);
scopeMappings = RoleUtils.expandCompositeRolesStream(scopeMappings);
// Intersection of expanded user roles and expanded scopeMappings
roleMappings.retainAll(scopeMappings);
roleMappings.retainAll(scopeMappings.collect(Collectors.toSet()));
return roleMappings;
}

View file

@ -40,8 +40,8 @@ import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.IOException;
import java.net.URI;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@ -58,7 +58,7 @@ public class KeycloakOIDCClientInstallation implements ClientInstallationProvide
if (client.isPublicClient() && !client.isBearerOnly()) rep.setPublicClient(true);
if (client.isBearerOnly()) rep.setBearerOnly(true);
if (client.getRoles().size() > 0) rep.setUseResourceRoleMappings(true);
if (client.getRolesStream().count() > 0) rep.setUseResourceRoleMappings(true);
rep.setResource(client.getClientId());
@ -104,7 +104,7 @@ public class KeycloakOIDCClientInstallation implements ClientInstallationProvide
static boolean showVerifyTokenAudience(ClientModel client) {
// We want to verify-token-audience if service client has any client roles
if (client.getRoles().size() > 0) {
if (client.getRolesStream().count() > 0) {
return true;
}
@ -187,13 +187,21 @@ public class KeycloakOIDCClientInstallation implements ClientInstallationProvide
rep.setEnforcerConfig(enforcerConfig);
Set<RoleModel> clientRoles = client.getRoles();
Iterator<RoleModel> it = client.getRolesStream().iterator();
if (clientRoles.size() == 1) {
if (clientRoles.iterator().next().getName().equals(Constants.AUTHZ_UMA_PROTECTION)) {
rep.setUseResourceRoleMappings(null);
}
RoleModel role = hasOnlyOne(it);
if (role != null && role.getName().equals(Constants.AUTHZ_UMA_PROTECTION)) {
rep.setUseResourceRoleMappings(null);
}
}
}
private RoleModel hasOnlyOne(Iterator<RoleModel> it) {
if (!it.hasNext()) return null;
else {
RoleModel role = it.next();
if (it.hasNext()) return null;
else return role;
}
}
}

View file

@ -53,7 +53,7 @@ public class KeycloakOIDCJbossSubsystemClientCliInstallation implements ClientIn
if (KeycloakOIDCClientInstallation.showVerifyTokenAudience(client)) {
builder.append(" verify-token-audience=true, \\\n");
}
if (client.getRoles().size() > 0) {
if (client.getRolesStream().count() > 0) {
builder.append(" use-resource-role-mappings=true, \\\n");
}
builder.append(" ssl-required=").append(realm.getSslRequired().name()).append(")\n\n");

View file

@ -73,7 +73,7 @@ public class KeycloakOIDCJbossSubsystemClientInstallation implements ClientInsta
}
}
}
if (client.getRoles().size() > 0) {
if (client.getRolesStream().count() > 0) {
buffer.append(" <use-resource-role-mappings>true</use-resource-role-mappings>\n");
}
buffer.append("</secure-deployment>\n");

View file

@ -31,6 +31,7 @@ import java.net.URI;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
@ -70,13 +71,11 @@ public class RedirectUtils {
}
private static Set<String> getValidateRedirectUris(KeycloakSession session) {
Set<String> redirects = new HashSet<>();
for (ClientModel client : session.getContext().getRealm().getClients()) {
if (client.isEnabled()) {
redirects.addAll(resolveValidRedirects(session, client.getRootUrl(), client.getRedirectUris()));
}
}
return redirects;
return session.getContext().getRealm().getClientsStream()
.filter(ClientModel::isEnabled)
.map(c -> resolveValidRedirects(session, c.getRootUrl(), c.getRedirectUris()))
.flatMap(Collection::stream)
.collect(Collectors.toSet());
}
private static String verifyRedirectUri(KeycloakSession session, String rootUrl, String redirectUri, Set<String> validRedirects, boolean requireRedirectUri) {

View file

@ -22,7 +22,6 @@ import org.jboss.resteasy.annotations.cache.NoCache;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.keycloak.common.VerificationException;
import org.keycloak.common.util.PemUtils;
import org.keycloak.common.util.StreamUtil;
import org.keycloak.crypto.KeyStatus;
import org.keycloak.dom.saml.v2.SAML2Object;
import org.keycloak.dom.saml.v2.assertion.BaseIDAbstractType;
@ -75,7 +74,6 @@ import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.security.PublicKey;
@ -83,21 +81,16 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.Properties;
import java.util.Set;
import java.util.TreeSet;
import org.keycloak.common.util.StringPropertyReplacer;
import org.keycloak.crypto.Algorithm;
import org.keycloak.crypto.KeyUse;
import org.keycloak.crypto.KeyWrapper;
import org.keycloak.dom.saml.v2.metadata.KeyTypes;
import org.keycloak.rotation.HardcodedKeyLocator;
import org.keycloak.rotation.KeyLocator;
import org.keycloak.saml.SPMetadataDescriptor;
import org.keycloak.saml.processing.core.util.KeycloakKeySamlExtensionGenerator;
import org.keycloak.saml.validators.DestinationValidator;
import org.keycloak.sessions.AuthenticationSessionModel;
import java.nio.charset.StandardCharsets;
import javax.ws.rs.core.MultivaluedMap;
import javax.xml.crypto.dsig.XMLSignature;
import org.w3c.dom.Document;
@ -698,16 +691,11 @@ public class SamlService extends AuthorizationEndpointBase {
public Response idpInitiatedSSO(@PathParam("client") String clientUrlName, @QueryParam("RelayState") String relayState) {
event.event(EventType.LOGIN);
CacheControlUtil.noBackButtonCacheControlHeader();
ClientModel client = null;
for (ClientModel c : realm.getClients()) {
String urlName = c.getAttribute(SamlProtocol.SAML_IDP_INITIATED_SSO_URL_NAME);
if (urlName == null)
continue;
if (urlName.equals(clientUrlName)) {
client = c;
break;
}
}
ClientModel client = realm.getClientsStream()
.filter(c -> Objects.nonNull(c.getAttribute(SamlProtocol.SAML_IDP_INITIATED_SSO_URL_NAME)))
.filter(c -> Objects.equals(c.getAttribute(SamlProtocol.SAML_IDP_INITIATED_SSO_URL_NAME), clientUrlName))
.findFirst().orElse(null);
if (client == null) {
event.error(Errors.CLIENT_NOT_FOUND);
return ErrorPage.error(session, null, Response.Status.BAD_REQUEST, Messages.CLIENT_NOT_FOUND);

View file

@ -42,7 +42,7 @@ public class MaxClientsClientRegistrationPolicy implements ClientRegistrationPol
@Override
public void beforeRegister(ClientRegistrationContext context) throws ClientRegistrationPolicyException {
RealmModel realm = session.getContext().getRealm();
int currentCount = realm.getClients().size();
long currentCount = realm.getClientsCount();
int maxCount = componentModel.get(MaxClientsClientRegistrationPolicyFactory.MAX_CLIENTS, MaxClientsClientRegistrationPolicyFactory.DEFAULT_MAX_CLIENTS);
if (currentCount >= maxCount) {

View file

@ -292,7 +292,7 @@ public class ClientManager {
if (clientModel.isPublicClient() && !clientModel.isBearerOnly()) rep.setPublicClient(true);
if (clientModel.isBearerOnly()) rep.setBearerOnly(true);
if (clientModel.getRoles().size() > 0) rep.setUseResourceRoleMappings(true);
if (clientModel.getRolesStream().count() > 0) rep.setUseResourceRoleMappings(true);
rep.setResource(clientModel.getClientId());
@ -336,7 +336,7 @@ public class ClientManager {
}
}
}
if (clientModel.getRoles().size() > 0) {
if (clientModel.getRolesStream().count() > 0) {
buffer.append(" <use-resource-role-mappings>true</use-resource-role-mappings>\n");
}
buffer.append("</secure-deployment>\n");

View file

@ -59,6 +59,8 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Stream;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@ -267,14 +269,17 @@ public class ResourceAdminManager {
public GlobalRequestResult logoutAll(RealmModel realm) {
realm.setNotBefore(Time.currentTime());
List<ClientModel> resources = realm.getClients();
logger.debugv("logging out {0} resources ", resources.size());
Stream<ClientModel> resources = realm.getClientsStream();
GlobalRequestResult finalResult = new GlobalRequestResult();
for (ClientModel resource : resources) {
GlobalRequestResult currentResult = logoutClient(realm, resource, realm.getNotBefore());
AtomicInteger counter = new AtomicInteger(0);
resources.forEach(r -> {
counter.getAndIncrement();
GlobalRequestResult currentResult = logoutClient(realm, r, realm.getNotBefore());
finalResult.addAll(currentResult);
}
});
logger.debugv("logging out {0} resources ", counter);
return finalResult;
}
@ -328,10 +333,10 @@ public class ResourceAdminManager {
public GlobalRequestResult pushRealmRevocationPolicy(RealmModel realm) {
GlobalRequestResult finalResult = new GlobalRequestResult();
for (ClientModel client : realm.getClients()) {
GlobalRequestResult currentResult = pushRevocationPolicy(realm, client, realm.getNotBefore());
realm.getClientsStream().forEach(c -> {
GlobalRequestResult currentResult = pushRevocationPolicy(realm, c, realm.getNotBefore());
finalResult.addAll(currentResult);
}
});
return finalResult;
}

View file

@ -22,7 +22,6 @@ import org.jboss.resteasy.spi.HttpRequest;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.keycloak.OAuthErrorException;
import org.keycloak.authentication.AuthenticationProcessor;
import org.keycloak.authentication.AuthenticationFlowException;
import org.keycloak.authentication.authenticators.broker.AbstractIdpAuthenticator;
import org.keycloak.authentication.authenticators.broker.util.PostBrokerLoginConstants;
import org.keycloak.authentication.authenticators.broker.util.SerializedBrokeredIdentityContext;
@ -1120,7 +1119,7 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
private ParsedCodeContext samlIdpInitiatedSSO(final String clientUrlName) {
event.event(EventType.LOGIN);
CacheControlUtil.noBackButtonCacheControlHeader();
Optional<ClientModel> oClient = this.realmModel.getClients().stream()
Optional<ClientModel> oClient = this.realmModel.getClientsStream()
.filter(c -> Objects.equals(c.getAttribute(SamlProtocol.SAML_IDP_INITIATED_SSO_URL_NAME), clientUrlName))
.findFirst();

View file

@ -515,10 +515,7 @@ public class AccountRestService {
consentModels.put(client.getClientId(), consent);
}
List<ClientModel> alwaysDisplayClients = realm.getAlwaysDisplayInConsoleClients();
for(ClientModel client : alwaysDisplayClients) {
clients.add(client);
}
realm.getAlwaysDisplayInConsoleClientsStream().forEach(clients::add);
List<ClientRepresentation> apps = new LinkedList<ClientRepresentation>();
for (ClientModel client : clients) {

View file

@ -53,18 +53,17 @@ import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.ext.Providers;
import java.io.IOException;
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;
import java.util.Set;
import java.util.stream.Collectors;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@ -219,7 +218,7 @@ public class AdminConsole {
if (realm.equals(masterRealm)) {
logger.debug("setting up realm access for a master realm user");
createRealm = user.hasRole(masterRealm.getRole(AdminRoles.CREATE_REALM));
addMasterRealmAccess(realm, user, realmAccess);
addMasterRealmAccess(user, realmAccess);
} else {
logger.debug("setting up realm access for a realm user");
addRealmAccess(realm, user, realmAccess);
@ -233,28 +232,26 @@ public class AdminConsole {
private void addRealmAccess(RealmModel realm, UserModel user, Map<String, Set<String>> realmAdminAccess) {
RealmManager realmManager = new RealmManager(session);
ClientModel realmAdminApp = realm.getClientByClientId(realmManager.getRealmAdminClientId(realm));
Set<RoleModel> roles = realmAdminApp.getRoles();
for (RoleModel role : roles) {
if (!user.hasRole(role)) continue;
if (!realmAdminAccess.containsKey(realm.getName())) {
realmAdminAccess.put(realm.getName(), new HashSet<String>());
}
realmAdminAccess.get(realm.getName()).add(role.getName());
}
getRealmAdminAccess(realmAdminApp, user, realmAdminAccess);
}
private void addMasterRealmAccess(RealmModel masterRealm, UserModel user, Map<String, Set<String>> realmAdminAccess) {
private void addMasterRealmAccess(UserModel user, Map<String, Set<String>> realmAdminAccess) {
List<RealmModel> realms = session.realms().getRealms();
for (RealmModel realm : realms) {
ClientModel realmAdminApp = realm.getMasterAdminClient();
Set<RoleModel> roles = realmAdminApp.getRoles();
for (RoleModel role : roles) {
if (!user.hasRole(role)) continue;
if (!realmAdminAccess.containsKey(realm.getName())) {
realmAdminAccess.put(realm.getName(), new HashSet<String>());
}
realmAdminAccess.get(realm.getName()).add(role.getName());
getRealmAdminAccess(realmAdminApp, user, realmAdminAccess);
}
}
private void getRealmAdminAccess(ClientModel client, UserModel user, Map<String, Set<String>> realmAdminAccess) {
Set<String> roles = client.getRolesStream().filter(user::hasRole)
.map(RoleModel::getName).collect(Collectors.toSet());
if (!roles.isEmpty()) {
if (!realmAdminAccess.containsKey(realm.getName())) {
realmAdminAccess.put(realm.getName(), roles);
} else {
realmAdminAccess.get(realm.getName()).addAll(roles);
}
}
}

View file

@ -19,7 +19,6 @@ package org.keycloak.services.resources.admin;
import org.jboss.logging.Logger;
import org.jboss.resteasy.annotations.cache.NoCache;
import javax.ws.rs.BadRequestException;
import javax.ws.rs.NotFoundException;
import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
import org.keycloak.events.admin.OperationType;
@ -46,14 +45,13 @@ import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Stream;
/**
* @resource Client Role Mappings
@ -120,17 +118,13 @@ public class ClientRoleMappingsResource {
@GET
@Produces(MediaType.APPLICATION_JSON)
@NoCache
public List<RoleRepresentation> getCompositeClientRoleMappings(@QueryParam("briefRepresentation") @DefaultValue("true") boolean briefRepresentation) {
public Stream<RoleRepresentation> getCompositeClientRoleMappings(@QueryParam("briefRepresentation") @DefaultValue("true") boolean briefRepresentation) {
viewPermission.require();
Set<RoleModel> roles = client.getRoles();
List<RoleRepresentation> mapRep = new ArrayList<RoleRepresentation>();
for (RoleModel roleModel : roles) {
if (user.hasRole(roleModel)) {
mapRep.add(briefRepresentation ? ModelToRepresentation.toBriefRepresentation(roleModel) : ModelToRepresentation.toRepresentation(roleModel));
}
}
return mapRep;
Stream<RoleModel> roles = client.getRolesStream();
Function<RoleModel, RoleRepresentation> toBriefRepresentation = briefRepresentation
? ModelToRepresentation::toBriefRepresentation : ModelToRepresentation::toRepresentation;
return roles.filter(user::hasRole).map(toBriefRepresentation);
}
/**
@ -142,28 +136,13 @@ public class ClientRoleMappingsResource {
@GET
@Produces(MediaType.APPLICATION_JSON)
@NoCache
public List<RoleRepresentation> getAvailableClientRoleMappings() {
public Stream<RoleRepresentation> getAvailableClientRoleMappings() {
viewPermission.require();
Set<RoleModel> available = client.getRoles();
available = available.stream().filter(r ->
auth.roles().canMapRole(r)
).collect(Collectors.toSet());
return getAvailableRoles(user, available);
}
public static List<RoleRepresentation> getAvailableRoles(RoleMapperModel mapper, Set<RoleModel> available) {
Set<RoleModel> roles = new HashSet<RoleModel>();
for (RoleModel roleModel : available) {
if (mapper.hasRole(roleModel)) continue;
roles.add(roleModel);
}
List<RoleRepresentation> mappings = new ArrayList<RoleRepresentation>();
for (RoleModel roleModel : roles) {
mappings.add(ModelToRepresentation.toBriefRepresentation(roleModel));
}
return mappings;
return client.getRolesStream()
.filter(auth.roles()::canMapRole)
.filter(((Predicate<RoleModel>) user::hasRole).negate())
.map(ModelToRepresentation::toBriefRepresentation);
}
/**

View file

@ -17,10 +17,11 @@
package org.keycloak.services.resources.admin;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.function.BiPredicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
@ -33,7 +34,6 @@ import org.keycloak.models.ClientScopeModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RoleContainerModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.ScopeContainerModel;
import org.keycloak.models.utils.ModelToRepresentation;
import org.keycloak.protocol.oidc.TokenManager;
import org.keycloak.representations.idm.RoleRepresentation;
@ -92,44 +92,32 @@ public class ClientScopeEvaluateScopeMappingsResource {
@GET
@Produces(MediaType.APPLICATION_JSON)
@NoCache
public List<RoleRepresentation> getNotGrantedScopeMappings() {
List<RoleModel> grantedRoles = getGrantedRoles();
public Stream<RoleRepresentation> getNotGrantedScopeMappings() {
Set<RoleModel> grantedRoles = getGrantedRoles();
return roleContainer.getRoles().stream().filter((RoleModel role) -> {
return !grantedRoles.contains(role);
}).map((RoleModel role) -> {
return ModelToRepresentation.toBriefRepresentation(role);
}).collect(Collectors.toList());
return roleContainer.getRolesStream()
.filter(r -> !grantedRoles.contains(r))
.map(ModelToRepresentation::toBriefRepresentation);
}
private List<RoleModel> getGrantedRoles() {
private Set<RoleModel> getGrantedRoles() {
if (client.isFullScopeAllowed()) {
return new LinkedList<>(roleContainer.getRoles());
// intentionally using deprecated method as a set is more appropriate here
return roleContainer.getRoles();
}
Set<ClientScopeModel> clientScopes = TokenManager.getRequestedClientScopes(scopeParam, client);
List<RoleModel> result = new LinkedList<>();
BiPredicate<Set<ClientScopeModel>, RoleModel> hasClientScope = (scopes, role) ->
scopes.stream().anyMatch(scopeContainer -> scopeContainer.hasScope(role));
for (RoleModel role : roleContainer.getRoles()) {
if (!auth.roles().canView(role)) continue;
for (ScopeContainerModel scopeContainer : clientScopes) {
if (scopeContainer.hasScope(role)) {
result.add(role);
break;
}
}
}
return result;
return roleContainer.getRolesStream()
.filter(auth.roles()::canView)
.filter(r -> hasClientScope.test(clientScopes, r))
.collect(Collectors.toSet());
}
}

View file

@ -36,7 +36,6 @@ import org.keycloak.services.ErrorResponseException;
import org.keycloak.services.ForbiddenException;
import org.keycloak.services.clientpolicy.AdminClientRegisterContext;
import org.keycloak.services.clientpolicy.ClientPolicyException;
import org.keycloak.services.clientpolicy.DefaultClientPolicyManager;
import org.keycloak.services.managers.ClientManager;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
@ -57,10 +56,9 @@ import javax.ws.rs.QueryParam;
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.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Properties;
import java.util.stream.Stream;
import static java.lang.Boolean.TRUE;
@ -101,65 +99,57 @@ public class ClientsResource {
@GET
@Produces(MediaType.APPLICATION_JSON)
@NoCache
public List<ClientRepresentation> getClients(@QueryParam("clientId") String clientId,
public Stream<ClientRepresentation> getClients(@QueryParam("clientId") String clientId,
@QueryParam("viewableOnly") @DefaultValue("false") boolean viewableOnly,
@QueryParam("search") @DefaultValue("false") boolean search,
@QueryParam("first") Integer firstResult,
@QueryParam("max") Integer maxResults) {
if (firstResult == null) {
firstResult = -1;
}
if (maxResults == null) {
maxResults = -1;
}
List<ClientRepresentation> rep = new ArrayList<>();
boolean canView = auth.clients().canView();
List<ClientModel> clientModels;
Stream<ClientModel> clientModels = Stream.empty();
if (clientId == null || clientId.trim().equals("")) {
clientModels = canView ? realm.getClients(firstResult, maxResults) : realm.getClients();
clientModels = canView
? realm.getClientsStream(firstResult, maxResults)
: realm.getClientsStream();
auth.clients().requireList();
} else if (search) {
clientModels = canView
? realm.searchClientByClientIdStream(clientId, firstResult, maxResults)
: realm.searchClientByClientIdStream(clientId, -1, -1);
} else {
clientModels = Collections.emptyList();
if(search) {
clientModels = canView ? realm.searchClientByClientId(clientId, firstResult, maxResults) : realm.searchClientByClientId(clientId, -1, -1);
} else {
ClientModel client = realm.getClientByClientId(clientId);
if(client != null) {
clientModels = Collections.singletonList(client);
}
ClientModel client = realm.getClientByClientId(clientId);
if (client != null) {
clientModels = Stream.of(client);
}
}
int idx = 0;
Stream<ClientRepresentation> s = clientModels
.map(c -> {
ClientRepresentation representation = null;
if (canView || auth.clients().canView(c)) {
representation = ModelToRepresentation.toRepresentation(c, session);
representation.setAccess(auth.clients().getAccess(c));
} else if (!viewableOnly && auth.clients().canView(c)) {
representation = new ClientRepresentation();
representation.setId(c.getId());
representation.setClientId(c.getClientId());
representation.setDescription(c.getDescription());
}
for(ClientModel clientModel : clientModels) {
if (!canView) {
if (rep.size() == maxResults) {
return rep;
}
return representation;
})
.filter(Objects::nonNull);
if (!canView) {
if (firstResult != null && firstResult > 0) {
s = s.skip(firstResult);
}
ClientRepresentation representation = null;
if (canView || auth.clients().canView(clientModel)) {
representation = ModelToRepresentation.toRepresentation(clientModel, session);
representation.setAccess(auth.clients().getAccess(clientModel));
} else if (!viewableOnly && auth.clients().canView(clientModel)) {
representation = new ClientRepresentation();
representation.setId(clientModel.getId());
representation.setClientId(clientModel.getClientId());
representation.setDescription(clientModel.getDescription());
}
if (representation != null) {
if (canView || idx++ >= firstResult) {
rep.add(representation);
}
if (maxResults != null && maxResults > 0) {
s = s.limit(maxResults);
}
}
return rep;
return s;
}
private AuthorizationService getAuthorizationService(ClientModel clientModel) {

View file

@ -100,20 +100,20 @@ public class RoleContainerResource extends RoleResource {
@QueryParam("briefRepresentation") @DefaultValue("true") boolean briefRepresentation) {
auth.roles().requireList(roleContainer);
Set<RoleModel> roleModels;
Stream<RoleModel> roleModels;
if(search != null && search.trim().length() > 0) {
roleModels = roleContainer.searchForRoles(search, firstResult, maxResults);
roleModels = roleContainer.searchForRolesStream(search, firstResult, maxResults);
} else if (!Objects.isNull(firstResult) && !Objects.isNull(maxResults)) {
roleModels = roleContainer.getRoles(firstResult, maxResults);
roleModels = roleContainer.getRolesStream(firstResult, maxResults);
} else {
roleModels = roleContainer.getRoles();
roleModels = roleContainer.getRolesStream();
}
Function<RoleModel, RoleRepresentation> toRoleRepresentation = briefRepresentation ?
ModelToRepresentation::toBriefRepresentation :
ModelToRepresentation::toRepresentation;
return roleModels.stream().map(toRoleRepresentation);
return roleModels.map(toRoleRepresentation);
}
/**

View file

@ -19,7 +19,6 @@ package org.keycloak.services.resources.admin;
import org.jboss.logging.Logger;
import org.jboss.resteasy.annotations.cache.NoCache;
import javax.ws.rs.BadRequestException;
import javax.ws.rs.NotFoundException;
import org.keycloak.common.ClientConnection;
import org.keycloak.events.admin.OperationType;
@ -35,7 +34,6 @@ import org.keycloak.models.utils.ModelToRepresentation;
import org.keycloak.representations.idm.ClientMappingsRepresentation;
import org.keycloak.representations.idm.MappingsRepresentation;
import org.keycloak.representations.idm.RoleRepresentation;
import org.keycloak.services.ErrorResponse;
import org.keycloak.services.ErrorResponseException;
import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
import org.keycloak.storage.ReadOnlyException;
@ -53,15 +51,15 @@ 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.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Stream;
/**
* Base resource for managing users
@ -183,17 +181,12 @@ public class RoleMapperResource {
@GET
@Produces(MediaType.APPLICATION_JSON)
@NoCache
public List<RoleRepresentation> getCompositeRealmRoleMappings(@QueryParam("briefRepresentation") @DefaultValue("true") boolean briefRepresentation) {
public Stream<RoleRepresentation> getCompositeRealmRoleMappings(@QueryParam("briefRepresentation") @DefaultValue("true") boolean briefRepresentation) {
viewPermission.require();
Set<RoleModel> roles = realm.getRoles();
List<RoleRepresentation> realmMappingsRep = new ArrayList<RoleRepresentation>();
for (RoleModel roleModel : roles) {
if (roleMapper.hasRole(roleModel)) {
realmMappingsRep.add(briefRepresentation ? ModelToRepresentation.toBriefRepresentation(roleModel) : ModelToRepresentation.toRepresentation(roleModel));
}
}
return realmMappingsRep;
Function<RoleModel, RoleRepresentation> toBriefRepresentation = briefRepresentation ?
ModelToRepresentation::toBriefRepresentation : ModelToRepresentation::toRepresentation;
return realm.getRolesStream().filter(roleMapper::hasRole).map(toBriefRepresentation);
}
/**
@ -205,14 +198,13 @@ public class RoleMapperResource {
@GET
@Produces(MediaType.APPLICATION_JSON)
@NoCache
public List<RoleRepresentation> getAvailableRealmRoleMappings() {
public Stream<RoleRepresentation> getAvailableRealmRoleMappings() {
viewPermission.require();
Set<RoleModel> available = realm.getRoles();
Set<RoleModel> set = available.stream().filter(r ->
canMapRole(r)
).collect(Collectors.toSet());
return ClientRoleMappingsResource.getAvailableRoles(roleMapper, set);
return realm.getRolesStream()
.filter(this::canMapRole)
.filter(((Predicate<RoleModel>) roleMapper::hasRole).negate())
.map(ModelToRepresentation::toBriefRepresentation);
}
/**

View file

@ -44,6 +44,9 @@ import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Stream;
/**
* @resource Scope Mappings
@ -105,11 +108,13 @@ public class ScopeMappedClientResource {
@GET
@Produces(MediaType.APPLICATION_JSON)
@NoCache
public List<RoleRepresentation> getAvailableClientScopeMappings() {
public Stream<RoleRepresentation> getAvailableClientScopeMappings() {
viewPermission.require();
Set<RoleModel> roles = scopedClient.getRoles();
return ScopeMappedResource.getAvailable(auth, scopeContainer, roles);
return scopedClient.getRolesStream()
.filter(((Predicate<RoleModel>) scopeContainer::hasScope).negate())
.filter(auth.roles()::canMapClientScope)
.map(ModelToRepresentation::toBriefRepresentation);
}
/**
@ -125,11 +130,14 @@ public class ScopeMappedClientResource {
@GET
@Produces(MediaType.APPLICATION_JSON)
@NoCache
public List<RoleRepresentation> getCompositeClientScopeMappings(@QueryParam("briefRepresentation") @DefaultValue("true") boolean briefRepresentation) {
public Stream<RoleRepresentation> getCompositeClientScopeMappings(@QueryParam("briefRepresentation") @DefaultValue("true") boolean briefRepresentation) {
viewPermission.require();
Set<RoleModel> roles = scopedClient.getRoles();
return ScopeMappedResource.getComposite(scopeContainer, roles, briefRepresentation);
Function<RoleModel, RoleRepresentation> toBriefRepresentation = briefRepresentation ?
ModelToRepresentation::toBriefRepresentation : ModelToRepresentation::toRepresentation;
return scopedClient.getRolesStream()
.filter(scopeContainer::hasScope)
.map(toBriefRepresentation);
}
/**

View file

@ -26,12 +26,12 @@ import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.ScopeContainerModel;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.models.utils.ModelToRepresentation;
import org.keycloak.representations.idm.ClientMappingsRepresentation;
import org.keycloak.representations.idm.MappingsRepresentation;
import org.keycloak.representations.idm.RoleRepresentation;
import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
import org.keycloak.services.util.ScopeMappedUtil;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
@ -44,11 +44,15 @@ import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
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;
/**
* Base class for managing the scope mappings of a specific client.
@ -97,32 +101,22 @@ public class ScopeMappedResource {
MappingsRepresentation all = new MappingsRepresentation();
Set<RoleModel> realmMappings = scopeContainer.getRealmScopeMappings();
if (realmMappings.size() > 0) {
List<RoleRepresentation> realmRep = new ArrayList<RoleRepresentation>();
if (!realmMappings.isEmpty()) {
List<RoleRepresentation> realmRep = new LinkedList<>();
for (RoleModel roleModel : realmMappings) {
realmRep.add(ModelToRepresentation.toBriefRepresentation(roleModel));
}
all.setRealmMappings(realmRep);
}
List<ClientModel> clients = realm.getClients();
if (clients.size() > 0) {
Map<String, ClientMappingsRepresentation> clientMappings = new HashMap<String, ClientMappingsRepresentation>();
for (ClientModel client : clients) {
Set<RoleModel> roleMappings = KeycloakModelUtils.getClientScopeMappings(client, this.scopeContainer); //client.getClientScopeMappings(this.client);
if (roleMappings.size() > 0) {
ClientMappingsRepresentation mappings = new ClientMappingsRepresentation();
mappings.setId(client.getId());
mappings.setClient(client.getClientId());
List<RoleRepresentation> roles = new ArrayList<RoleRepresentation>();
mappings.setMappings(roles);
for (RoleModel role : roleMappings) {
roles.add(ModelToRepresentation.toBriefRepresentation(role));
}
clientMappings.put(client.getClientId(), mappings);
all.setClientMappings(clientMappings);
}
}
Stream<ClientModel> clients = realm.getClientsStream();
Map<String, ClientMappingsRepresentation> clientMappings = clients
.map(c -> ScopeMappedUtil.toClientMappingsRepresentation(c, scopeContainer))
.filter(Objects::nonNull)
.collect(Collectors.toMap(ClientMappingsRepresentation::getClient, Function.identity()));
if (!clientMappings.isEmpty()) {
all.setClientMappings(clientMappings);
}
return all;
}
@ -160,25 +154,17 @@ public class ScopeMappedResource {
@GET
@Produces(MediaType.APPLICATION_JSON)
@NoCache
public List<RoleRepresentation> getAvailableRealmScopeMappings() {
public Stream<RoleRepresentation> getAvailableRealmScopeMappings() {
viewPermission.require();
if (scopeContainer == null) {
throw new NotFoundException("Could not find client");
}
Set<RoleModel> roles = realm.getRoles();
return getAvailable(auth, scopeContainer, roles);
}
public static List<RoleRepresentation> getAvailable(AdminPermissionEvaluator auth, ScopeContainerModel client, Set<RoleModel> roles) {
List<RoleRepresentation> available = new ArrayList<RoleRepresentation>();
for (RoleModel roleModel : roles) {
if (client.hasScope(roleModel)) continue;
if (!auth.roles().canMapClientScope(roleModel)) continue;
available.add(ModelToRepresentation.toBriefRepresentation(roleModel));
}
return available;
return realm.getRolesStream()
.filter(((Predicate<RoleModel>) scopeContainer::hasScope).negate())
.filter(auth.roles()::canMapClientScope)
.map(ModelToRepresentation::toBriefRepresentation);
}
/**
@ -196,23 +182,18 @@ public class ScopeMappedResource {
@GET
@Produces(MediaType.APPLICATION_JSON)
@NoCache
public List<RoleRepresentation> getCompositeRealmScopeMappings(@QueryParam("briefRepresentation") @DefaultValue("true") boolean briefRepresentation) {
public Stream<RoleRepresentation> getCompositeRealmScopeMappings(@QueryParam("briefRepresentation") @DefaultValue("true") boolean briefRepresentation) {
viewPermission.require();
if (scopeContainer == null) {
throw new NotFoundException("Could not find client");
}
Set<RoleModel> roles = realm.getRoles();
return getComposite(scopeContainer, roles, briefRepresentation);
}
public static List<RoleRepresentation> getComposite(ScopeContainerModel client, Set<RoleModel> roles, boolean briefRepresentation) {
List<RoleRepresentation> composite = new ArrayList<RoleRepresentation>();
for (RoleModel roleModel : roles) {
if (client.hasScope(roleModel)) composite.add(briefRepresentation ? ModelToRepresentation.toBriefRepresentation(roleModel) : ModelToRepresentation.toRepresentation(roleModel));
}
return composite;
Function<RoleModel, RoleRepresentation> toBriefRepresentation = briefRepresentation ?
ModelToRepresentation::toBriefRepresentation : ModelToRepresentation::toRepresentation;
return realm.getRolesStream()
.filter(scopeContainer::hasScope)
.map(toBriefRepresentation);
}
/**

View file

@ -466,40 +466,40 @@ public class UserResource {
@Produces(MediaType.APPLICATION_JSON)
public List<Map<String, Object>> getConsents() {
auth.users().requireView(user);
List<Map<String, Object>> result = new LinkedList<>();
Set<ClientModel> offlineClients = new UserSessionManager(session).findClientsWithOfflineToken(realm, user);
for (ClientModel client : realm.getClients()) {
UserConsentModel consent = session.users().getConsentByClient(realm, user.getId(), client.getId());
boolean hasOfflineToken = offlineClients.contains(client);
return realm.getClientsStream()
.map(client -> toConsent(client, offlineClients))
.filter(Objects::nonNull)
.collect(Collectors.toList());
}
if (consent == null && !hasOfflineToken) {
continue;
}
private Map<String, Object> toConsent(ClientModel client, Set<ClientModel> offlineClients) {
UserConsentModel consent = session.users().getConsentByClient(realm, user.getId(), client.getId());
boolean hasOfflineToken = offlineClients.contains(client);
UserConsentRepresentation rep = (consent == null) ? null : ModelToRepresentation.toRepresentation(consent);
Map<String, Object> currentRep = new HashMap<>();
currentRep.put("clientId", client.getClientId());
currentRep.put("grantedClientScopes", (rep==null ? Collections.emptyList() : rep.getGrantedClientScopes()));
currentRep.put("createdDate", (rep==null ? null : rep.getCreatedDate()));
currentRep.put("lastUpdatedDate", (rep==null ? null : rep.getLastUpdatedDate()));
List<Map<String, String>> additionalGrants = new LinkedList<>();
if (hasOfflineToken) {
Map<String, String> offlineTokens = new HashMap<>();
offlineTokens.put("client", client.getId());
// TODO: translate
offlineTokens.put("key", "Offline Token");
additionalGrants.add(offlineTokens);
}
currentRep.put("additionalGrants", additionalGrants);
result.add(currentRep);
if (consent == null && !hasOfflineToken) {
return null;
}
return result;
UserConsentRepresentation rep = (consent == null) ? null : ModelToRepresentation.toRepresentation(consent);
Map<String, Object> currentRep = new HashMap<>();
currentRep.put("clientId", client.getClientId());
currentRep.put("grantedClientScopes", (rep == null ? Collections.emptyList() : rep.getGrantedClientScopes()));
currentRep.put("createdDate", (rep == null ? null : rep.getCreatedDate()));
currentRep.put("lastUpdatedDate", (rep == null ? null : rep.getLastUpdatedDate()));
List<Map<String, String>> additionalGrants = new LinkedList<>();
if (hasOfflineToken) {
Map<String, String> offlineTokens = new HashMap<>();
offlineTokens.put("client", client.getId());
offlineTokens.put("key", "Offline Token");
additionalGrants.add(offlineTokens);
}
currentRep.put("additionalGrants", additionalGrants);
return currentRep;
}

View file

@ -0,0 +1,52 @@
/*
* Copyright 2020 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.services.util;
import org.keycloak.models.ClientModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.ScopeContainerModel;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.models.utils.ModelToRepresentation;
import org.keycloak.representations.idm.ClientMappingsRepresentation;
import org.keycloak.representations.idm.RoleRepresentation;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
public class ScopeMappedUtil {
public static ClientMappingsRepresentation toClientMappingsRepresentation(ClientModel client, ScopeContainerModel scopeContainer) {
Set<RoleModel> roleMappings = KeycloakModelUtils.getClientScopeMappings(client, scopeContainer);
if (!roleMappings.isEmpty()) {
ClientMappingsRepresentation mappings = new ClientMappingsRepresentation();
mappings.setId(client.getId());
mappings.setClient(client.getClientId());
List<RoleRepresentation> roles = new LinkedList<>();
mappings.setMappings(roles);
for (RoleModel role : roleMappings) {
roles.add(ModelToRepresentation.toBriefRepresentation(role));
}
return mappings;
} else {
return null;
}
}
}

View file

@ -64,10 +64,11 @@ public class TestClientRolesCondition implements ClientPolicyConditionProvider {
List<String> rolesForMatching = getRolesForMatching();
if (rolesForMatching == null) return false;
client.getRoles().stream().forEach(i -> ClientPolicyLogger.log(logger, "client role = " + i.getName()));
client.getRolesStream().forEach(i -> ClientPolicyLogger.log(logger, "client role = " + i.getName()));
rolesForMatching.stream().forEach(i -> ClientPolicyLogger.log(logger, "roles expected = " + i));
boolean isMatched = rolesForMatching.stream().anyMatch(i->client.getRoles().stream().anyMatch(j->j.getName().equals(i)));
boolean isMatched = rolesForMatching.stream()
.anyMatch(i -> client.getRolesStream().anyMatch(j -> j.getName().equals(i)));
if (isMatched) {
ClientPolicyLogger.log(logger, "role matched.");
} else {

View file

@ -34,6 +34,7 @@ import org.keycloak.testsuite.arquillian.annotation.ModelTest;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Stream;
import static org.keycloak.testsuite.admin.AbstractAdminTest.loadJson;
import org.keycloak.testsuite.arquillian.annotation.AuthServerContainerExclude.AuthServer;
@ -52,17 +53,14 @@ public class CompositeRolesModelTest extends AbstractTestRealmKeycloakTest {
Set<RoleModel> requestedRoles = new HashSet<>();
Set<RoleModel> roleMappings = user.getRoleMappings();
Set<RoleModel> scopeMappings = application.getScopeMappings();
Set<RoleModel> appRoles = application.getRoles();
if (appRoles != null) scopeMappings.addAll(appRoles);
Stream<RoleModel> scopeMappings = Stream.concat(application.getScopeMappingsStream(), application.getRolesStream());
for (RoleModel role : roleMappings) {
scopeMappings.forEach(scope -> roleMappings.forEach(role -> {
if (role.getContainer().equals(application)) requestedRoles.add(role);
for (RoleModel desiredRole : scopeMappings) {
Set<RoleModel> visited = new HashSet<>();
applyScope(role, desiredRole, visited, requestedRoles);
}
}
Set<RoleModel> visited = new HashSet<>();
applyScope(role, scope, visited, requestedRoles);
}));
return requestedRoles;
}

View file

@ -24,7 +24,6 @@ import org.keycloak.models.GroupModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleContainerModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserModel;
/**
@ -35,12 +34,12 @@ public class TestCacheUtils {
public static void cacheRealmWithEverything(KeycloakSession session, String realmName) {
RealmModel realm = session.realms().getRealmByName(realmName);
for (ClientModel client : realm.getClients()) {
realm.getClientById(client.getId());
realm.getClientByClientId(client.getClientId());
realm.getClientsStream().forEach(c -> {
realm.getClientById(c.getId());
realm.getClientByClientId(c.getClientId());
cacheRoles(session, realm, client);
}
cacheRoles(session, realm, c);
});
cacheRoles(session, realm, realm);
@ -66,7 +65,7 @@ public class TestCacheUtils {
}
private static void cacheRoles(KeycloakSession session, RealmModel realm, RoleContainerModel roleContainer) {
for (RoleModel role : roleContainer.getRoles()) {
roleContainer.getRolesStream().forEach(role -> {
realm.getRoleById(role.getId());
roleContainer.getRole(role.getName());
if (roleContainer instanceof RealmModel) {
@ -74,7 +73,7 @@ public class TestCacheUtils {
} else {
session.roles().getClientRole((ClientModel) roleContainer, role.getName());
}
}
});
}
private static void cacheGroupRecursive(RealmModel realm, GroupModel group) {