template scope
This commit is contained in:
1 parent
0527d441e3
commit
d939b6a431
42 files changed
+1294
-132
No files matched your search
@@ -8,7 +8,7 @@ import java.util.Set;
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public interface ClientModel extends RoleContainerModel, ProtocolMapperContainerModel {
|
||||
public interface ClientModel extends RoleContainerModel, ProtocolMapperContainerModel, ScopeContainerModel {
|
||||
|
||||
// COMMON ATTRIBUTES
|
||||
|
||||
@@ -74,7 +74,6 @@ public interface ClientModel extends RoleContainerModel, ProtocolMapperContaine
|
||||
|
||||
void updateDefaultRoles(String[] defaultRoles);
|
||||
|
||||
Set<RoleModel> getClientScopeMappings(ClientModel client);
|
||||
|
||||
boolean isBearerOnly();
|
||||
void setBearerOnly(boolean only);
|
||||
@@ -93,9 +92,6 @@ public interface ClientModel extends RoleContainerModel, ProtocolMapperContaine
|
||||
String getRegistrationToken();
|
||||
void setRegistrationToken(String registrationToken);
|
||||
|
||||
boolean isFullScopeAllowed();
|
||||
void setFullScopeAllowed(boolean value);
|
||||
|
||||
String getProtocol();
|
||||
void setProtocol(String protocol);
|
||||
|
||||
@@ -126,16 +122,16 @@ public interface ClientModel extends RoleContainerModel, ProtocolMapperContaine
|
||||
boolean isServiceAccountsEnabled();
|
||||
void setServiceAccountsEnabled(boolean serviceAccountsEnabled);
|
||||
|
||||
Set<RoleModel> getScopeMappings();
|
||||
void addScopeMapping(RoleModel role);
|
||||
void deleteScopeMapping(RoleModel role);
|
||||
Set<RoleModel> getRealmScopeMappings();
|
||||
boolean hasScope(RoleModel role);
|
||||
|
||||
RealmModel getRealm();
|
||||
|
||||
ClientTemplateModel getClientTemplate();
|
||||
void setClientTemplate(ClientTemplateModel template);
|
||||
boolean useTemplateScope();
|
||||
void setUseTemplateScope(boolean flag);
|
||||
boolean useTemplateMappers();
|
||||
void setUseTemplateMappers(boolean flag);
|
||||
boolean useTemplateConfig();
|
||||
void setUseTemplateConfig(boolean flag);
|
||||
|
||||
/**
|
||||
* Time in seconds since epoc
|
||||
|
||||
@@ -8,7 +8,7 @@ import java.util.Set;
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public interface ClientTemplateModel extends ProtocolMapperContainerModel {
|
||||
public interface ClientTemplateModel extends ProtocolMapperContainerModel, ScopeContainerModel {
|
||||
String getId();
|
||||
|
||||
String getName();
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package org.keycloak.models;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public interface ScopeContainerModel {
|
||||
boolean isFullScopeAllowed();
|
||||
|
||||
void setFullScopeAllowed(boolean value);
|
||||
|
||||
Set<RoleModel> getScopeMappings();
|
||||
|
||||
void addScopeMapping(RoleModel role);
|
||||
|
||||
void deleteScopeMapping(RoleModel role);
|
||||
|
||||
Set<RoleModel> getRealmScopeMappings();
|
||||
|
||||
boolean hasScope(RoleModel role);
|
||||
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package org.keycloak.models;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public interface ScopeMapperModel {
|
||||
|
||||
}
|
||||
@@ -49,6 +49,9 @@ public class ClientEntity extends AbstractIdentifiableEntity {
|
||||
private List<ClientIdentityProviderMappingEntity> identityProviders = new ArrayList<ClientIdentityProviderMappingEntity>();
|
||||
private List<ProtocolMapperEntity> protocolMappers = new ArrayList<ProtocolMapperEntity>();
|
||||
private String clientTemplate;
|
||||
private boolean useTemplateConfig;
|
||||
private boolean useTemplateScope;
|
||||
private boolean useTemplateMappers;
|
||||
|
||||
public String getClientId() {
|
||||
return clientId;
|
||||
@@ -309,5 +312,29 @@ public class ClientEntity extends AbstractIdentifiableEntity {
|
||||
public void setClientTemplate(String clientTemplate) {
|
||||
this.clientTemplate = clientTemplate;
|
||||
}
|
||||
|
||||
public boolean isUseTemplateConfig() {
|
||||
return useTemplateConfig;
|
||||
}
|
||||
|
||||
public void setUseTemplateConfig(boolean useTemplateConfig) {
|
||||
this.useTemplateConfig = useTemplateConfig;
|
||||
}
|
||||
|
||||
public boolean isUseTemplateScope() {
|
||||
return useTemplateScope;
|
||||
}
|
||||
|
||||
public void setUseTemplateScope(boolean useTemplateScope) {
|
||||
this.useTemplateScope = useTemplateScope;
|
||||
}
|
||||
|
||||
public boolean isUseTemplateMappers() {
|
||||
return useTemplateMappers;
|
||||
}
|
||||
|
||||
public void setUseTemplateMappers(boolean useTemplateMappers) {
|
||||
this.useTemplateMappers = useTemplateMappers;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,8 @@ public class ClientTemplateEntity extends AbstractIdentifiableEntity {
|
||||
private String description;
|
||||
private String realmId;
|
||||
private String protocol;
|
||||
private boolean fullScopeAllowed;
|
||||
private List<String> scopeIds = new ArrayList<String>();
|
||||
private List<ProtocolMapperEntity> protocolMappers = new ArrayList<ProtocolMapperEntity>();
|
||||
|
||||
public String getName() {
|
||||
@@ -55,5 +57,21 @@ public class ClientTemplateEntity extends AbstractIdentifiableEntity {
|
||||
public void setProtocol(String protocol) {
|
||||
this.protocol = protocol;
|
||||
}
|
||||
|
||||
public boolean isFullScopeAllowed() {
|
||||
return fullScopeAllowed;
|
||||
}
|
||||
|
||||
public void setFullScopeAllowed(boolean fullScopeAllowed) {
|
||||
this.fullScopeAllowed = fullScopeAllowed;
|
||||
}
|
||||
|
||||
public List<String> getScopeIds() {
|
||||
return scopeIds;
|
||||
}
|
||||
|
||||
public void setScopeIds(List<String> scopeIds) {
|
||||
this.scopeIds = scopeIds;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,9 @@ import org.keycloak.models.KeycloakSessionTask;
|
||||
import org.keycloak.models.KeycloakTransaction;
|
||||
import org.keycloak.models.ModelDuplicateException;
|
||||
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;
|
||||
import org.keycloak.models.UserFederationMapperModel;
|
||||
import org.keycloak.models.UserFederationProviderModel;
|
||||
@@ -38,6 +40,7 @@ import java.security.SecureRandom;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -521,4 +524,20 @@ public final class KeycloakModelUtils {
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
public static Set<RoleModel> getClientScopeMappings(ClientModel client, ScopeContainerModel container) {
|
||||
Set<RoleModel> mappings = container.getScopeMappings();
|
||||
Set<RoleModel> result = new HashSet<>();
|
||||
for (RoleModel role : mappings) {
|
||||
RoleContainerModel roleContainer = role.getContainer();
|
||||
if (roleContainer instanceof ClientModel) {
|
||||
if (client.getId().equals(((ClientModel)roleContainer).getId())) {
|
||||
result.add(role);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -419,6 +419,7 @@ public class ModelToRepresentation {
|
||||
}
|
||||
rep.setProtocolMappers(mappings);
|
||||
}
|
||||
rep.setFullScopeAllowed(clientModel.isFullScopeAllowed());
|
||||
|
||||
return rep;
|
||||
}
|
||||
@@ -476,6 +477,9 @@ public class ModelToRepresentation {
|
||||
}
|
||||
rep.setProtocolMappers(mappings);
|
||||
}
|
||||
rep.setUseTemplateMappers(clientModel.useTemplateMappers());
|
||||
rep.setUseTemplateConfig(clientModel.useTemplateConfig());
|
||||
rep.setUseTemplateScope(clientModel.useTemplateScope());
|
||||
|
||||
return rep;
|
||||
}
|
||||
|
||||
@@ -802,11 +802,6 @@ public class RepresentationToModel {
|
||||
if (resourceRep.isPublicClient() != null) client.setPublicClient(resourceRep.isPublicClient());
|
||||
if (resourceRep.isFrontchannelLogout() != null) client.setFrontchannelLogout(resourceRep.isFrontchannelLogout());
|
||||
if (resourceRep.getProtocol() != null) client.setProtocol(resourceRep.getProtocol());
|
||||
if (resourceRep.isFullScopeAllowed() != null) {
|
||||
client.setFullScopeAllowed(resourceRep.isFullScopeAllowed());
|
||||
} else {
|
||||
client.setFullScopeAllowed(!client.isConsentRequired());
|
||||
}
|
||||
if (resourceRep.getNodeReRegistrationTimeout() != null) {
|
||||
client.setNodeReRegistrationTimeout(resourceRep.getNodeReRegistrationTimeout());
|
||||
} else {
|
||||
@@ -893,6 +888,26 @@ public class RepresentationToModel {
|
||||
}
|
||||
}
|
||||
|
||||
if (resourceRep.isFullScopeAllowed() != null) {
|
||||
client.setFullScopeAllowed(resourceRep.isFullScopeAllowed());
|
||||
} else {
|
||||
if (client.getClientTemplate() != null) {
|
||||
client.setFullScopeAllowed(!client.isConsentRequired() && client.getClientTemplate().isFullScopeAllowed());
|
||||
|
||||
} else {
|
||||
client.setFullScopeAllowed(!client.isConsentRequired());
|
||||
}
|
||||
}
|
||||
if (resourceRep.isUseTemplateConfig() != null) client.setUseTemplateConfig(resourceRep.isUseTemplateConfig());
|
||||
else client.setUseTemplateConfig(resourceRep.getClientTemplate() != null);
|
||||
|
||||
if (resourceRep.isUseTemplateScope() != null) client.setUseTemplateScope(resourceRep.isUseTemplateScope());
|
||||
else client.setUseTemplateScope(resourceRep.getClientTemplate() != null);
|
||||
|
||||
if (resourceRep.isUseTemplateMappers() != null) client.setUseTemplateMappers(resourceRep.isUseTemplateMappers());
|
||||
else client.setUseTemplateMappers(resourceRep.getClientTemplate() != null);
|
||||
|
||||
|
||||
return client;
|
||||
}
|
||||
|
||||
@@ -949,14 +964,23 @@ public class RepresentationToModel {
|
||||
}
|
||||
}
|
||||
|
||||
if (rep.isUseTemplateConfig() != null) resource.setUseTemplateConfig(rep.isUseTemplateConfig());
|
||||
if (rep.isUseTemplateScope() != null) resource.setUseTemplateScope(rep.isUseTemplateScope());
|
||||
if (rep.isUseTemplateMappers() != null) resource.setUseTemplateMappers(rep.isUseTemplateMappers());
|
||||
|
||||
|
||||
if (rep.getClientTemplate() != null) {
|
||||
if (rep.getClientTemplate().equals(ClientTemplateRepresentation.NONE)) {
|
||||
resource.setClientTemplate(null);
|
||||
} else {
|
||||
RealmModel realm = resource.getRealm();
|
||||
for (ClientTemplateModel template : realm.getClientTemplates()) {
|
||||
|
||||
if (template.getName().equals(rep.getClientTemplate())) {
|
||||
resource.setClientTemplate(template);
|
||||
if (rep.isUseTemplateConfig() == null) resource.setUseTemplateConfig(true);
|
||||
if (rep.isUseTemplateScope() == null) resource.setUseTemplateScope(true);
|
||||
if (rep.isUseTemplateMappers() == null) resource.setUseTemplateMappers(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -984,7 +1008,7 @@ public class RepresentationToModel {
|
||||
if (resourceRep.getName() != null) client.setName(resourceRep.getName());
|
||||
if(resourceRep.getDescription() != null) client.setDescription(resourceRep.getDescription());
|
||||
if (resourceRep.getProtocol() != null) client.setProtocol(resourceRep.getProtocol());
|
||||
|
||||
if (resourceRep.isFullScopeAllowed() != null) client.setFullScopeAllowed(resourceRep.isFullScopeAllowed());
|
||||
if (resourceRep.getProtocolMappers() != null) {
|
||||
// first, remove all default/built in mappers
|
||||
Set<ProtocolMapperModel> mappers = client.getProtocolMappers();
|
||||
@@ -1001,6 +1025,9 @@ public class RepresentationToModel {
|
||||
public static void updateClientTemplate(ClientTemplateRepresentation rep, ClientTemplateModel resource) {
|
||||
if (rep.getName() != null) resource.setName(rep.getName());
|
||||
if (rep.getDescription() != null) resource.setDescription(rep.getDescription());
|
||||
if (rep.isFullScopeAllowed() != null) {
|
||||
resource.setFullScopeAllowed(rep.isFullScopeAllowed());
|
||||
}
|
||||
|
||||
|
||||
if (rep.getProtocol() != null) resource.setProtocol(rep.getProtocol());
|
||||
|
||||
+41
-19
@@ -69,6 +69,47 @@ public class ClientAdapter implements ClientModel {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useTemplateScope() {
|
||||
if (updated != null) return updated.useTemplateScope();
|
||||
return cached.isUseTemplateScope();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUseTemplateScope(boolean value) {
|
||||
getDelegateForUpdate();
|
||||
updated.setUseTemplateScope(value);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useTemplateConfig() {
|
||||
if (updated != null) return updated.useTemplateConfig();
|
||||
return cached.isUseTemplateConfig();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUseTemplateConfig(boolean value) {
|
||||
getDelegateForUpdate();
|
||||
updated.setUseTemplateConfig(value);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useTemplateMappers() {
|
||||
if (updated != null) return updated.useTemplateMappers();
|
||||
return cached.isUseTemplateMappers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUseTemplateMappers(boolean value) {
|
||||
getDelegateForUpdate();
|
||||
updated.setUseTemplateMappers(value);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void addWebOrigin(String webOrigin) {
|
||||
getDelegateForUpdate();
|
||||
updated.addWebOrigin(webOrigin);
|
||||
@@ -412,25 +453,6 @@ public class ClientAdapter implements ClientModel {
|
||||
updated.updateDefaultRoles(defaultRoles);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<RoleModel> getClientScopeMappings(ClientModel client) {
|
||||
Set<RoleModel> roleMappings = client.getScopeMappings();
|
||||
|
||||
Set<RoleModel> appRoles = new HashSet<RoleModel>();
|
||||
for (RoleModel role : roleMappings) {
|
||||
RoleContainerModel container = role.getContainer();
|
||||
if (container instanceof RealmModel) {
|
||||
} else {
|
||||
ClientModel app = (ClientModel)container;
|
||||
if (app.getId().equals(getId())) {
|
||||
appRoles.add(role);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return appRoles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBearerOnly() {
|
||||
if (updated != null) return updated.isBearerOnly();
|
||||
|
||||
+64
@@ -132,6 +132,70 @@ public class ClientTemplateAdapter implements ClientTemplateModel {
|
||||
updated.setProtocol(protocol);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFullScopeAllowed() {
|
||||
if (updated != null) return updated.isFullScopeAllowed();
|
||||
return cached.isFullScopeAllowed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFullScopeAllowed(boolean value) {
|
||||
getDelegateForUpdate();
|
||||
updated.setFullScopeAllowed(value);
|
||||
|
||||
}
|
||||
|
||||
public Set<RoleModel> getScopeMappings() {
|
||||
if (updated != null) return updated.getScopeMappings();
|
||||
Set<RoleModel> roles = new HashSet<RoleModel>();
|
||||
for (String id : cached.getScope()) {
|
||||
roles.add(cacheSession.getRoleById(id, getRealm()));
|
||||
|
||||
}
|
||||
return roles;
|
||||
}
|
||||
|
||||
public void addScopeMapping(RoleModel role) {
|
||||
getDelegateForUpdate();
|
||||
updated.addScopeMapping(role);
|
||||
}
|
||||
|
||||
public void deleteScopeMapping(RoleModel role) {
|
||||
getDelegateForUpdate();
|
||||
updated.deleteScopeMapping(role);
|
||||
}
|
||||
|
||||
public Set<RoleModel> getRealmScopeMappings() {
|
||||
Set<RoleModel> roleMappings = getScopeMappings();
|
||||
|
||||
Set<RoleModel> appRoles = new HashSet<RoleModel>();
|
||||
for (RoleModel role : roleMappings) {
|
||||
RoleContainerModel container = role.getContainer();
|
||||
if (container instanceof RealmModel) {
|
||||
if (((RealmModel) container).getId().equals(cachedRealm.getId())) {
|
||||
appRoles.add(role);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return appRoles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasScope(RoleModel role) {
|
||||
if (updated != null) return updated.hasScope(role);
|
||||
if (cached.isFullScopeAllowed() || cached.getScope().contains(role.getId())) return true;
|
||||
|
||||
Set<RoleModel> roles = getScopeMappings();
|
||||
|
||||
for (RoleModel mapping : roles) {
|
||||
if (mapping.hasRole(role)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
|
||||
+18
@@ -56,6 +56,9 @@ public class CachedClient implements Serializable {
|
||||
private int nodeReRegistrationTimeout;
|
||||
private Map<String, Integer> registeredNodes;
|
||||
private String clientTemplate;
|
||||
private boolean useTemplateScope;
|
||||
private boolean useTemplateConfig;
|
||||
private boolean useTemplateMappers;
|
||||
|
||||
public CachedClient(RealmCache cache, RealmProvider delegate, RealmModel realm, ClientModel model) {
|
||||
id = model.getId();
|
||||
@@ -102,6 +105,9 @@ public class CachedClient implements Serializable {
|
||||
if (model.getClientTemplate() != null) {
|
||||
clientTemplate = model.getClientTemplate().getId();
|
||||
}
|
||||
useTemplateConfig = model.useTemplateConfig();
|
||||
useTemplateMappers = model.useTemplateMappers();
|
||||
useTemplateScope = model.useTemplateScope();
|
||||
}
|
||||
public String getId() {
|
||||
return id;
|
||||
@@ -238,4 +244,16 @@ public class CachedClient implements Serializable {
|
||||
public String getClientTemplate() {
|
||||
return clientTemplate;
|
||||
}
|
||||
|
||||
public boolean isUseTemplateScope() {
|
||||
return useTemplateScope;
|
||||
}
|
||||
|
||||
public boolean isUseTemplateConfig() {
|
||||
return useTemplateConfig;
|
||||
}
|
||||
|
||||
public boolean isUseTemplateMappers() {
|
||||
return useTemplateMappers;
|
||||
}
|
||||
}
|
||||
+14
@@ -28,6 +28,8 @@ public class CachedClientTemplate implements Serializable {
|
||||
private String description;
|
||||
private String realm;
|
||||
private String protocol;
|
||||
private boolean fullScopeAllowed;
|
||||
private Set<String> scope = new HashSet<String>();
|
||||
private Set<ProtocolMapperModel> protocolMappers = new HashSet<ProtocolMapperModel>();
|
||||
|
||||
public CachedClientTemplate(RealmCache cache, RealmProvider delegate, RealmModel realm, ClientTemplateModel model) {
|
||||
@@ -36,9 +38,13 @@ public class CachedClientTemplate implements Serializable {
|
||||
description = model.getDescription();
|
||||
this.realm = realm.getId();
|
||||
protocol = model.getProtocol();
|
||||
fullScopeAllowed = model.isFullScopeAllowed();
|
||||
for (ProtocolMapperModel mapper : model.getProtocolMappers()) {
|
||||
this.protocolMappers.add(mapper);
|
||||
}
|
||||
for (RoleModel role : model.getScopeMappings()) {
|
||||
scope.add(role.getId());
|
||||
}
|
||||
}
|
||||
public String getId() {
|
||||
return id;
|
||||
@@ -63,4 +69,12 @@ public class CachedClientTemplate implements Serializable {
|
||||
public String getProtocol() {
|
||||
return protocol;
|
||||
}
|
||||
|
||||
public boolean isFullScopeAllowed() {
|
||||
return fullScopeAllowed;
|
||||
}
|
||||
|
||||
public Set<String> getScope() {
|
||||
return scope;
|
||||
}
|
||||
}
|
||||
@@ -206,7 +206,7 @@ public class ClientAdapter implements ClientModel {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<RoleModel> getRealmScopeMappings() {
|
||||
public Set<RoleModel> getRealmScopeMappings() {
|
||||
Set<RoleModel> roleMappings = getScopeMappings();
|
||||
|
||||
Set<RoleModel> appRoles = new HashSet<>();
|
||||
@@ -238,7 +238,8 @@ public class ClientAdapter implements ClientModel {
|
||||
|
||||
@Override
|
||||
public void addScopeMapping(RoleModel role) {
|
||||
if (hasScope(role)) return;
|
||||
Set<RoleModel> roles = getScopeMappings();
|
||||
if (roles.contains(role)) return;
|
||||
ScopeMappingEntity entity = new ScopeMappingEntity();
|
||||
entity.setClient(getEntity());
|
||||
RoleEntity roleEntity = RoleAdapter.toRoleEntity(role, em);
|
||||
@@ -319,6 +320,39 @@ public class ClientAdapter implements ClientModel {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useTemplateScope() {
|
||||
return entity.isUseTemplateScope();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUseTemplateScope(boolean flag) {
|
||||
entity.setUseTemplateScope(flag);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useTemplateMappers() {
|
||||
return entity.isUseTemplateMappers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUseTemplateMappers(boolean flag) {
|
||||
entity.setUseTemplateMappers(flag);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useTemplateConfig() {
|
||||
return entity.isUseTemplateConfig();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUseTemplateConfig(boolean flag) {
|
||||
entity.setUseTemplateConfig(flag);
|
||||
|
||||
}
|
||||
|
||||
public static boolean contains(String str, String[] array) {
|
||||
for (String s : array) {
|
||||
if (str.equals(s)) return true;
|
||||
@@ -604,6 +638,7 @@ public class ClientAdapter implements ClientModel {
|
||||
String compositeRoleTable = JpaUtils.getTableNameForNativeQuery("COMPOSITE_ROLE", em);
|
||||
em.createNativeQuery("delete from " + compositeRoleTable + " where CHILD_ROLE = :role").setParameter("role", role).executeUpdate();
|
||||
em.createNamedQuery("deleteScopeMappingByRole").setParameter("role", role).executeUpdate();
|
||||
em.createNamedQuery("deleteTemplateScopeMappingByRole").setParameter("role", role).executeUpdate();
|
||||
role.setClient(null);
|
||||
em.flush();
|
||||
em.remove(role);
|
||||
@@ -641,28 +676,6 @@ public class ClientAdapter implements ClientModel {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<RoleModel> getClientScopeMappings(ClientModel client) {
|
||||
Set<RoleModel> roleMappings = client.getScopeMappings();
|
||||
|
||||
Set<RoleModel> appRoles = new HashSet<RoleModel>();
|
||||
for (RoleModel role : roleMappings) {
|
||||
RoleContainerModel container = role.getContainer();
|
||||
if (container instanceof RealmModel) {
|
||||
} else {
|
||||
ClientModel app = (ClientModel)container;
|
||||
if (app.getId().equals(getId())) {
|
||||
appRoles.add(role);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return appRoles;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public List<String> getDefaultRoles() {
|
||||
Collection<RoleEntity> entities = entity.getDefaultRoles();
|
||||
|
||||
@@ -14,6 +14,7 @@ import org.keycloak.models.jpa.entities.ClientTemplateEntity;
|
||||
import org.keycloak.models.jpa.entities.ProtocolMapperEntity;
|
||||
import org.keycloak.models.jpa.entities.RoleEntity;
|
||||
import org.keycloak.models.jpa.entities.ScopeMappingEntity;
|
||||
import org.keycloak.models.jpa.entities.TemplateScopeMappingEntity;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
@@ -203,6 +204,88 @@ public class ClientTemplateAdapter implements ClientTemplateModel {
|
||||
return mapping;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFullScopeAllowed() {
|
||||
return entity.isFullScopeAllowed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFullScopeAllowed(boolean value) {
|
||||
entity.setFullScopeAllowed(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<RoleModel> getRealmScopeMappings() {
|
||||
Set<RoleModel> roleMappings = getScopeMappings();
|
||||
|
||||
Set<RoleModel> appRoles = new HashSet<>();
|
||||
for (RoleModel role : roleMappings) {
|
||||
RoleContainerModel container = role.getContainer();
|
||||
if (container instanceof RealmModel) {
|
||||
if (((RealmModel) container).getId().equals(realm.getId())) {
|
||||
appRoles.add(role);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return appRoles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<RoleModel> getScopeMappings() {
|
||||
TypedQuery<String> query = em.createNamedQuery("clientTemplateScopeMappingIds", String.class);
|
||||
query.setParameter("template", getEntity());
|
||||
List<String> ids = query.getResultList();
|
||||
Set<RoleModel> roles = new HashSet<RoleModel>();
|
||||
for (String roleId : ids) {
|
||||
RoleModel role = realm.getRoleById(roleId);
|
||||
if (role == null) continue;
|
||||
roles.add(role);
|
||||
}
|
||||
return roles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addScopeMapping(RoleModel role) {
|
||||
if (hasScope(role)) return;
|
||||
TemplateScopeMappingEntity entity = new TemplateScopeMappingEntity();
|
||||
entity.setTemplate(getEntity());
|
||||
RoleEntity roleEntity = RoleAdapter.toRoleEntity(role, em);
|
||||
entity.setRole(roleEntity);
|
||||
em.persist(entity);
|
||||
em.flush();
|
||||
em.detach(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteScopeMapping(RoleModel role) {
|
||||
TypedQuery<TemplateScopeMappingEntity> query = getRealmScopeMappingQuery(role);
|
||||
List<TemplateScopeMappingEntity> results = query.getResultList();
|
||||
if (results.size() == 0) return;
|
||||
for (TemplateScopeMappingEntity entity : results) {
|
||||
em.remove(entity);
|
||||
}
|
||||
}
|
||||
|
||||
protected TypedQuery<TemplateScopeMappingEntity> getRealmScopeMappingQuery(RoleModel role) {
|
||||
TypedQuery<TemplateScopeMappingEntity> query = em.createNamedQuery("templateHasScope", TemplateScopeMappingEntity.class);
|
||||
query.setParameter("template", getEntity());
|
||||
RoleEntity roleEntity = RoleAdapter.toRoleEntity(role, em);
|
||||
query.setParameter("role", roleEntity);
|
||||
return query;
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
@@ -219,4 +302,6 @@ public class ClientTemplateAdapter implements ClientTemplateModel {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -110,6 +110,9 @@ public class JpaRealmProvider implements RealmProvider {
|
||||
for (ClientEntity a : new LinkedList<>(realm.getClients())) {
|
||||
adapter.removeClient(a.getId());
|
||||
}
|
||||
for (ClientTemplateEntity a : new LinkedList<>(realm.getClientTemplates())) {
|
||||
adapter.removeClientTemplate(a.getId());
|
||||
}
|
||||
|
||||
em.remove(realm);
|
||||
|
||||
|
||||
@@ -1051,6 +1051,7 @@ public class RealmAdapter implements RealmModel {
|
||||
String compositeRoleTable = JpaUtils.getTableNameForNativeQuery("COMPOSITE_ROLE", em);
|
||||
em.createNativeQuery("delete from " + compositeRoleTable + " where CHILD_ROLE = :role").setParameter("role", roleEntity).executeUpdate();
|
||||
em.createNamedQuery("deleteScopeMappingByRole").setParameter("role", roleEntity).executeUpdate();
|
||||
em.createNamedQuery("deleteTemplateScopeMappingByRole").setParameter("role", roleEntity).executeUpdate();
|
||||
em.createNamedQuery("deleteGroupRoleMappingsByRole").setParameter("roleId", roleEntity.getId()).executeUpdate();
|
||||
|
||||
em.remove(roleEntity);
|
||||
@@ -2146,9 +2147,12 @@ public class RealmAdapter implements RealmModel {
|
||||
if (client == null) {
|
||||
return false;
|
||||
}
|
||||
em.createNamedQuery("deleteTemplateScopeMappingByClient").setParameter("template", clientEntity).executeUpdate();
|
||||
em.flush();
|
||||
em.remove(clientEntity);
|
||||
em.flush();
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -61,6 +61,15 @@ public class ClientEntity {
|
||||
@JoinColumn(name = "CLIENT_TEMPLATE_ID")
|
||||
protected ClientTemplateEntity clientTemplate;
|
||||
|
||||
@Column(name="USE_TEMPLATE_CONFIG")
|
||||
private boolean useTemplateConfig;
|
||||
|
||||
@Column(name="USE_TEMPLATE_SCOPE")
|
||||
private boolean useTemplateScope;
|
||||
|
||||
@Column(name="USE_TEMPLATE_MAPPERS")
|
||||
private boolean useTemplateMappers;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "REALM_ID")
|
||||
protected RealmEntity realm;
|
||||
@@ -404,4 +413,28 @@ public class ClientEntity {
|
||||
public void setClientTemplate(ClientTemplateEntity clientTemplate) {
|
||||
this.clientTemplate = clientTemplate;
|
||||
}
|
||||
|
||||
public boolean isUseTemplateConfig() {
|
||||
return useTemplateConfig;
|
||||
}
|
||||
|
||||
public void setUseTemplateConfig(boolean useTemplateConfig) {
|
||||
this.useTemplateConfig = useTemplateConfig;
|
||||
}
|
||||
|
||||
public boolean isUseTemplateScope() {
|
||||
return useTemplateScope;
|
||||
}
|
||||
|
||||
public void setUseTemplateScope(boolean useTemplateScope) {
|
||||
this.useTemplateScope = useTemplateScope;
|
||||
}
|
||||
|
||||
public boolean isUseTemplateMappers() {
|
||||
return useTemplateMappers;
|
||||
}
|
||||
|
||||
public void setUseTemplateMappers(boolean useTemplateMappers) {
|
||||
this.useTemplateMappers = useTemplateMappers;
|
||||
}
|
||||
}
|
||||
@@ -45,6 +45,8 @@ public class ClientTemplateEntity {
|
||||
@Column(name="PROTOCOL")
|
||||
private String protocol;
|
||||
|
||||
@Column(name="FULL_SCOPE_ALLOWED")
|
||||
private boolean fullScopeAllowed;
|
||||
|
||||
public RealmEntity getRealm() {
|
||||
return realm;
|
||||
@@ -93,4 +95,12 @@ public class ClientTemplateEntity {
|
||||
public void setProtocol(String protocol) {
|
||||
this.protocol = protocol;
|
||||
}
|
||||
|
||||
public boolean isFullScopeAllowed() {
|
||||
return fullScopeAllowed;
|
||||
}
|
||||
|
||||
public void setFullScopeAllowed(boolean fullScopeAllowed) {
|
||||
this.fullScopeAllowed = fullScopeAllowed;
|
||||
}
|
||||
}
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
package org.keycloak.models.jpa.entities;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.IdClass;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.NamedQueries;
|
||||
import javax.persistence.NamedQuery;
|
||||
import javax.persistence.Table;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
@NamedQueries({
|
||||
@NamedQuery(name="templateHasScope", query="select m from TemplateScopeMappingEntity m where m.template = :template and m.role = :role"),
|
||||
@NamedQuery(name="clientTemplateScopeMappings", query="select m from TemplateScopeMappingEntity m where m.template = :template"),
|
||||
@NamedQuery(name="clientTemplateScopeMappingIds", query="select m.role.id from TemplateScopeMappingEntity m where m.template = :template"),
|
||||
@NamedQuery(name="deleteTemplateScopeMappingByRole", query="delete from TemplateScopeMappingEntity where role = :role"),
|
||||
@NamedQuery(name="deleteTemplateScopeMappingByClient", query="delete from TemplateScopeMappingEntity where template = :template")
|
||||
})
|
||||
@Table(name="TEMPLATE_SCOPE_MAPPING")
|
||||
@Entity
|
||||
@IdClass(TemplateScopeMappingEntity.Key.class)
|
||||
public class TemplateScopeMappingEntity {
|
||||
|
||||
@Id
|
||||
@ManyToOne(fetch= FetchType.LAZY)
|
||||
@JoinColumn(name = "TEMPLATE_ID")
|
||||
protected ClientTemplateEntity template;
|
||||
|
||||
@Id
|
||||
@ManyToOne(fetch= FetchType.LAZY)
|
||||
@JoinColumn(name="ROLE_ID")
|
||||
protected RoleEntity role;
|
||||
|
||||
public ClientTemplateEntity getTemplate() {
|
||||
return template;
|
||||
}
|
||||
|
||||
public void setTemplate(ClientTemplateEntity template) {
|
||||
this.template = template;
|
||||
}
|
||||
|
||||
public RoleEntity getRole() {
|
||||
return role;
|
||||
}
|
||||
|
||||
public void setRole(RoleEntity role) {
|
||||
this.role = role;
|
||||
}
|
||||
|
||||
public static class Key implements Serializable {
|
||||
|
||||
protected ClientTemplateEntity template;
|
||||
|
||||
protected RoleEntity role;
|
||||
|
||||
public Key() {
|
||||
}
|
||||
|
||||
public Key(ClientTemplateEntity template, RoleEntity role) {
|
||||
this.template = template;
|
||||
this.role = role;
|
||||
}
|
||||
|
||||
public ClientTemplateEntity getTemplate() {
|
||||
return template;
|
||||
}
|
||||
|
||||
public RoleEntity getRole() {
|
||||
return role;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
Key key = (Key) o;
|
||||
|
||||
if (template != null ? !template.getId().equals(key.template != null ? key.template.getId() : null) : key.template != null) return false;
|
||||
if (role != null ? !role.getId().equals(key.role != null ? key.role.getId() : null) : key.role != null) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = template != null ? template.getId().hashCode() : 0;
|
||||
result = 31 * result + (role != null ? role.getId().hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+38
-13
@@ -10,6 +10,7 @@ import org.keycloak.models.ModelDuplicateException;
|
||||
import org.keycloak.models.ProtocolMapperModel;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.ScopeContainerModel;
|
||||
import org.keycloak.models.entities.ProtocolMapperEntity;
|
||||
import org.keycloak.models.mongo.keycloak.entities.MongoClientEntity;
|
||||
import org.keycloak.models.mongo.keycloak.entities.MongoRoleEntity;
|
||||
@@ -620,19 +621,6 @@ public class ClientAdapter extends AbstractMongoAdapter<MongoClientEntity> imple
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<RoleModel> getClientScopeMappings(ClientModel client) {
|
||||
Set<RoleModel> result = new HashSet<RoleModel>();
|
||||
List<MongoRoleEntity> roles = MongoModelUtils.getAllScopesOfClient(client, invocationContext);
|
||||
|
||||
for (MongoRoleEntity role : roles) {
|
||||
if (getId().equals(role.getClientId())) {
|
||||
result.add(new RoleAdapter(session, getRealm(), role, this, invocationContext));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getDefaultRoles() {
|
||||
return getMongoEntity().getDefaultRoles();
|
||||
@@ -726,4 +714,41 @@ public class ClientAdapter extends AbstractMongoAdapter<MongoClientEntity> imple
|
||||
updateMongoEntity();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useTemplateScope() {
|
||||
return getMongoEntity().isUseTemplateScope();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUseTemplateScope(boolean flag) {
|
||||
getMongoEntity().setUseTemplateScope(flag);
|
||||
updateMongoEntity();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useTemplateMappers() {
|
||||
return getMongoEntity().isUseTemplateMappers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUseTemplateMappers(boolean flag) {
|
||||
getMongoEntity().setUseTemplateMappers(flag);
|
||||
updateMongoEntity();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useTemplateConfig() {
|
||||
return getMongoEntity().isUseTemplateConfig();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUseTemplateConfig(boolean flag) {
|
||||
getMongoEntity().setUseTemplateConfig(flag);
|
||||
updateMongoEntity();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+63
@@ -209,7 +209,70 @@ public class ClientTemplateAdapter extends AbstractMongoAdapter<MongoClientTempl
|
||||
return mapping;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFullScopeAllowed() {
|
||||
return getMongoEntity().isFullScopeAllowed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFullScopeAllowed(boolean value) {
|
||||
getMongoEntity().setFullScopeAllowed(value);
|
||||
updateMongoEntity();
|
||||
|
||||
}
|
||||
@Override
|
||||
public Set<RoleModel> getScopeMappings() {
|
||||
Set<RoleModel> result = new HashSet<RoleModel>();
|
||||
List<MongoRoleEntity> roles = MongoModelUtils.getAllScopesOfTemplate(this, invocationContext);
|
||||
|
||||
for (MongoRoleEntity role : roles) {
|
||||
if (realm.getId().equals(role.getRealmId())) {
|
||||
result.add(new RoleAdapter(session, realm, role, realm, invocationContext));
|
||||
} else {
|
||||
// Likely applicationRole, but we don't have this application yet
|
||||
result.add(new RoleAdapter(session, realm, role, invocationContext));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<RoleModel> getRealmScopeMappings() {
|
||||
Set<RoleModel> allScopes = getScopeMappings();
|
||||
|
||||
// Filter to retrieve just realm roles TODO: Maybe improve to avoid filter programmatically... Maybe have separate fields for realmRoles and appRoles on user?
|
||||
Set<RoleModel> realmRoles = new HashSet<RoleModel>();
|
||||
for (RoleModel role : allScopes) {
|
||||
MongoRoleEntity roleEntity = ((RoleAdapter) role).getRole();
|
||||
|
||||
if (realm.getId().equals(roleEntity.getRealmId())) {
|
||||
realmRoles.add(role);
|
||||
}
|
||||
}
|
||||
return realmRoles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addScopeMapping(RoleModel role) {
|
||||
getMongoStore().pushItemToList(this.getMongoEntity(), "scopeIds", role.getId(), true, invocationContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteScopeMapping(RoleModel role) {
|
||||
getMongoStore().pullItemFromList(this.getMongoEntity(), "scopeIds", role.getId(), invocationContext);
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
|
||||
@@ -4,12 +4,15 @@ import com.mongodb.DBObject;
|
||||
import com.mongodb.QueryBuilder;
|
||||
import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
|
||||
import org.keycloak.models.ClientModel;
|
||||
import org.keycloak.models.ClientTemplateModel;
|
||||
import org.keycloak.models.GroupModel;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.entities.ClientEntity;
|
||||
import org.keycloak.models.entities.ClientTemplateEntity;
|
||||
import org.keycloak.models.mongo.keycloak.adapters.ClientAdapter;
|
||||
import org.keycloak.models.mongo.keycloak.adapters.ClientTemplateAdapter;
|
||||
import org.keycloak.models.mongo.keycloak.adapters.GroupAdapter;
|
||||
import org.keycloak.models.mongo.keycloak.adapters.UserAdapter;
|
||||
import org.keycloak.models.mongo.keycloak.entities.MongoRoleEntity;
|
||||
@@ -52,6 +55,19 @@ public class MongoModelUtils {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
DBObject query = new QueryBuilder()
|
||||
.and("_id").in(scopeIds)
|
||||
.get();
|
||||
return invContext.getMongoStore().loadEntities(MongoRoleEntity.class, query, invContext);
|
||||
}
|
||||
public static List<MongoRoleEntity> getAllScopesOfTemplate(ClientTemplateModel template, MongoStoreInvocationContext invContext) {
|
||||
ClientTemplateEntity scopedEntity = ((ClientTemplateAdapter)template).getMongoEntity();
|
||||
List<String> scopeIds = scopedEntity.getScopeIds();
|
||||
|
||||
if (scopeIds == null || scopeIds.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
DBObject query = new QueryBuilder()
|
||||
.and("_id").in(scopeIds)
|
||||
.get();
|
||||
|
||||
Reference in new issue
Block a user