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);
|
updated.addClientScope(clientScope, defaultScope);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addClientScopes(Set<ClientScopeModel> clientScopes, boolean defaultScope) {
|
||||||
|
for (ClientScopeModel clientScope : clientScopes) {
|
||||||
|
addClientScope(clientScope, defaultScope);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeClientScope(ClientScopeModel clientScope) {
|
public void removeClientScope(ClientScopeModel clientScope) {
|
||||||
getDelegateForUpdate();
|
getDelegateForUpdate();
|
||||||
|
|
|
@ -355,6 +355,18 @@ public class ClientAdapter implements ClientModel, JpaModel<ClientEntity> {
|
||||||
public void addClientScope(ClientScopeModel clientScope, boolean defaultScope) {
|
public void addClientScope(ClientScopeModel clientScope, boolean defaultScope) {
|
||||||
if (getClientScopes(defaultScope, false).containsKey(clientScope.getName())) return;
|
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();
|
ClientScopeClientMappingEntity entity = new ClientScopeClientMappingEntity();
|
||||||
entity.setClientScope(ClientScopeAdapter.toClientScopeEntity(clientScope, em));
|
entity.setClientScope(ClientScopeAdapter.toClientScopeEntity(clientScope, em));
|
||||||
entity.setClient(getEntity());
|
entity.setClient(getEntity());
|
||||||
|
|
|
@ -25,6 +25,12 @@ import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.provider.ProviderEvent;
|
import org.keycloak.provider.ProviderEvent;
|
||||||
import org.keycloak.provider.ProviderEventListener;
|
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>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
* @version $Revision: 1 $
|
* @version $Revision: 1 $
|
||||||
|
@ -56,9 +62,7 @@ public abstract class AbstractLoginProtocolFactory implements LoginProtocolFacto
|
||||||
|
|
||||||
// Create default client scopes for realm built-in clients too
|
// Create default client scopes for realm built-in clients too
|
||||||
if (addScopesToExistingClients) {
|
if (addScopesToExistingClients) {
|
||||||
for (ClientModel client : newRealm.getClients()) {
|
addDefaultClientScopes(newRealm, newRealm.getClients());
|
||||||
addDefaultClientScopes(newRealm, client);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,15 +73,22 @@ public abstract class AbstractLoginProtocolFactory implements LoginProtocolFacto
|
||||||
|
|
||||||
|
|
||||||
protected void addDefaultClientScopes(RealmModel realm, ClientModel newClient) {
|
protected void addDefaultClientScopes(RealmModel realm, ClientModel newClient) {
|
||||||
for (ClientScopeModel clientScope : realm.getDefaultClientScopes(true)) {
|
addDefaultClientScopes(realm, Arrays.asList(newClient));
|
||||||
if (getId().equals(clientScope.getProtocol())) {
|
}
|
||||||
newClient.addClientScope(clientScope, true);
|
|
||||||
}
|
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())) {
|
Set<ClientScopeModel> nonDefaultClientScopes = realm.getDefaultClientScopes(false).stream()
|
||||||
newClient.addClientScope(clientScope, false);
|
.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.models.RoleModel;
|
||||||
import org.keycloak.storage.ReadOnlyException;
|
import org.keycloak.storage.ReadOnlyException;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -224,6 +225,11 @@ public abstract class AbstractReadOnlyClientStorageAdapter extends AbstractClien
|
||||||
throw new ReadOnlyException("client is read only for this update");
|
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
|
@Override
|
||||||
public void removeClientScope(ClientScopeModel clientScope) {
|
public void removeClientScope(ClientScopeModel clientScope) {
|
||||||
throw new ReadOnlyException("client is read only for this update");
|
throw new ReadOnlyException("client is read only for this update");
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
package org.keycloak.models;
|
package org.keycloak.models;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
@ -170,6 +171,13 @@ public interface ClientModel extends ClientScopeModel, RoleContainerModel, Prot
|
||||||
*/
|
*/
|
||||||
void addClientScope(ClientScopeModel clientScope, boolean defaultScope);
|
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);
|
void removeClientScope(ClientScopeModel clientScope);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in a new issue