KEYCLOAK-13818: Addressing performance issues with adding client scopes during realm creation. Removing redundant lookups by passing all scopes that need to be created at once.
This commit is contained in:
parent
49db2c13a5
commit
3291161954
5 changed files with 55 additions and 11 deletions
|
@ -102,6 +102,13 @@ public class ClientAdapter implements ClientModel, CachedObject {
|
|||
updated.addClientScope(clientScope, defaultScope);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addClientScopes(Set<ClientScopeModel> clientScopes, boolean defaultScope) {
|
||||
for (ClientScopeModel clientScope : clientScopes) {
|
||||
addClientScope(clientScope, defaultScope);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeClientScope(ClientScopeModel clientScope) {
|
||||
getDelegateForUpdate();
|
||||
|
|
|
@ -355,6 +355,18 @@ public class ClientAdapter implements ClientModel, JpaModel<ClientEntity> {
|
|||
public void addClientScope(ClientScopeModel clientScope, boolean defaultScope) {
|
||||
if (getClientScopes(defaultScope, false).containsKey(clientScope.getName())) return;
|
||||
|
||||
persist(clientScope, defaultScope);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addClientScopes(Set<ClientScopeModel> clientScopes, boolean defaultScope) {
|
||||
Map<String, ClientScopeModel> existingClientScopes = getClientScopes(defaultScope, false);
|
||||
clientScopes.stream()
|
||||
.filter(clientScope -> !existingClientScopes.containsKey(clientScope.getName()))
|
||||
.forEach(clientScope -> persist(clientScope, defaultScope));
|
||||
}
|
||||
|
||||
private void persist(ClientScopeModel clientScope, boolean defaultScope) {
|
||||
ClientScopeClientMappingEntity entity = new ClientScopeClientMappingEntity();
|
||||
entity.setClientScope(ClientScopeAdapter.toClientScopeEntity(clientScope, em));
|
||||
entity.setClient(getEntity());
|
||||
|
|
|
@ -25,6 +25,12 @@ 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.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
|
@ -56,9 +62,7 @@ public abstract class AbstractLoginProtocolFactory implements LoginProtocolFacto
|
|||
|
||||
// Create default client scopes for realm built-in clients too
|
||||
if (addScopesToExistingClients) {
|
||||
for (ClientModel client : newRealm.getClients()) {
|
||||
addDefaultClientScopes(newRealm, client);
|
||||
}
|
||||
addDefaultClientScopes(newRealm, newRealm.getClients());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -69,15 +73,22 @@ public abstract class AbstractLoginProtocolFactory implements LoginProtocolFacto
|
|||
|
||||
|
||||
protected void addDefaultClientScopes(RealmModel realm, ClientModel newClient) {
|
||||
for (ClientScopeModel clientScope : realm.getDefaultClientScopes(true)) {
|
||||
if (getId().equals(clientScope.getProtocol())) {
|
||||
newClient.addClientScope(clientScope, true);
|
||||
addDefaultClientScopes(realm, Arrays.asList(newClient));
|
||||
}
|
||||
|
||||
protected void addDefaultClientScopes(RealmModel realm, List<ClientModel> newClients) {
|
||||
Set<ClientScopeModel> defaultClientScopes = realm.getDefaultClientScopes(true).stream()
|
||||
.filter(clientScope -> getId().equals(clientScope.getProtocol()))
|
||||
.collect(Collectors.toSet());
|
||||
for (ClientModel newClient : newClients) {
|
||||
newClient.addClientScopes(defaultClientScopes, true);
|
||||
}
|
||||
for (ClientScopeModel clientScope : realm.getDefaultClientScopes(false)) {
|
||||
if (getId().equals(clientScope.getProtocol())) {
|
||||
newClient.addClientScope(clientScope, false);
|
||||
}
|
||||
|
||||
Set<ClientScopeModel> nonDefaultClientScopes = realm.getDefaultClientScopes(false).stream()
|
||||
.filter(clientScope -> getId().equals(clientScope.getProtocol()))
|
||||
.collect(Collectors.toSet());
|
||||
for (ClientModel newClient : newClients) {
|
||||
newClient.addClientScopes(nonDefaultClientScopes, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ import org.keycloak.models.RealmModel;
|
|||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.storage.ReadOnlyException;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
|
@ -224,6 +225,11 @@ public abstract class AbstractReadOnlyClientStorageAdapter extends AbstractClien
|
|||
throw new ReadOnlyException("client is read only for this update");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addClientScopes(Set<ClientScopeModel> clientScopes, boolean defaultScope) {
|
||||
throw new ReadOnlyException("client is read only for this update");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeClientScope(ClientScopeModel clientScope) {
|
||||
throw new ReadOnlyException("client is read only for this update");
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
package org.keycloak.models;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -170,6 +171,13 @@ public interface ClientModel extends ClientScopeModel, RoleContainerModel, Prot
|
|||
*/
|
||||
void addClientScope(ClientScopeModel clientScope, boolean defaultScope);
|
||||
|
||||
/**
|
||||
* Add clientScopes with this client. Add as default scopes (if parameter 'defaultScope' is true) or optional scopes (if parameter 'defaultScope' is false)
|
||||
* @param clientScopes
|
||||
* @param defaultScope
|
||||
*/
|
||||
void addClientScopes(Set<ClientScopeModel> clientScopes, boolean defaultScope);
|
||||
|
||||
void removeClientScope(ClientScopeModel clientScope);
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in a new issue