KEYCLOAK-6630 Client scopes initial support (#5076)

* KEYCLOAK-6630 KEYCLOAK-349 Client Scopes

Co-authored-by: vramik <vramik@redhat.com>

* KEYCLOAK-6630 Change some clientTemplate occurences to clientScope
This commit is contained in:
Marek Posolda 2018-06-08 15:38:38 +02:00 committed by GitHub
parent 4d1474afe0
commit 49407c2e4f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
290 changed files with 8253 additions and 6812 deletions

View file

@ -250,7 +250,16 @@
baseUrl = kc.endpoints.authorize();
}
var scope = (options && options.scope) ? "openid " + options.scope : "openid";
var scope;
if (options && options.scope) {
if (options.scope.indexOf("openid") != -1) {
scope = options.scope;
} else {
scope = "openid " + options.scope;
}
} else {
scope = "openid";
}
var url = baseUrl
+ '?client_id=' + encodeURIComponent(kc.clientId)

View file

@ -97,6 +97,21 @@ public class AccessToken extends IDToken {
}
}
// KEYCLOAK-6771 Certificate Bound Token
// https://tools.ietf.org/html/draft-ietf-oauth-mtls-08#section-3.1
public static class CertConf {
@JsonProperty("x5t#S256")
protected String certThumbprint;
public String getCertThumbprint() {
return certThumbprint;
}
public void setCertThumbprint(String certThumbprint) {
this.certThumbprint = certThumbprint;
}
}
@JsonProperty("trusted-certs")
protected Set<String> trustedCertificates;
@ -112,6 +127,12 @@ public class AccessToken extends IDToken {
@JsonProperty("authorization")
protected Authorization authorization;
@JsonProperty("cnf")
protected CertConf certConf;
@JsonProperty("scope")
protected String scope;
public Map<String, Access> getResourceAccess() {
return resourceAccess;
}
@ -234,24 +255,6 @@ public class AccessToken extends IDToken {
this.authorization = authorization;
}
// KEYCLOAK-6771 Certificate Bound Token
// https://tools.ietf.org/html/draft-ietf-oauth-mtls-08#section-3.1
public static class CertConf {
@JsonProperty("x5t#S256")
protected String certThumbprint;
public String getCertThumbprint() {
return certThumbprint;
}
public void setCertThumbprint(String certThumbprint) {
this.certThumbprint = certThumbprint;
}
}
@JsonProperty("cnf")
protected CertConf certConf;
public CertConf getCertConf() {
return certConf;
}
@ -259,4 +262,12 @@ public class AccessToken extends IDToken {
public void setCertConf(CertConf certConf) {
this.certConf = certConf;
}
public String getScope() {
return scope;
}
public void setScope(String scope) {
this.scope = scope;
}
}

View file

@ -46,6 +46,7 @@ public class RefreshToken extends AccessToken {
this.sessionState = token.sessionState;
this.nonce = token.nonce;
this.audience = token.audience;
this.scope = token.scope;
if (token.realmAccess != null) {
realmAccess = token.realmAccess.clone();
}
@ -56,4 +57,5 @@ public class RefreshToken extends AccessToken {
}
}
}
}

View file

@ -61,10 +61,19 @@ public class ClientRepresentation {
protected Integer nodeReRegistrationTimeout;
protected Map<String, Integer> registeredNodes;
protected List<ProtocolMapperRepresentation> protocolMappers;
@Deprecated
protected String clientTemplate;
@Deprecated
private Boolean useTemplateConfig;
@Deprecated
private Boolean useTemplateScope;
@Deprecated
private Boolean useTemplateMappers;
protected List<String> defaultClientScopes;
protected List<String> optionalClientScopes;
private ResourceServerRepresentation authorizationSettings;
private Map<String, Boolean> access;
protected String origin;
@ -338,36 +347,40 @@ public class ClientRepresentation {
this.protocolMappers = protocolMappers;
}
@Deprecated
public String getClientTemplate() {
return clientTemplate;
}
public void setClientTemplate(String clientTemplate) {
this.clientTemplate = clientTemplate;
}
@Deprecated
public Boolean isUseTemplateConfig() {
return useTemplateConfig;
}
public void setUseTemplateConfig(Boolean useTemplateConfig) {
this.useTemplateConfig = useTemplateConfig;
}
@Deprecated
public Boolean isUseTemplateScope() {
return useTemplateScope;
}
public void setUseTemplateScope(Boolean useTemplateScope) {
this.useTemplateScope = useTemplateScope;
}
@Deprecated
public Boolean isUseTemplateMappers() {
return useTemplateMappers;
}
public void setUseTemplateMappers(Boolean useTemplateMappers) {
this.useTemplateMappers = useTemplateMappers;
public List<String> getDefaultClientScopes() {
return defaultClientScopes;
}
public void setDefaultClientScopes(List<String> defaultClientScopes) {
this.defaultClientScopes = defaultClientScopes;
}
public List<String> getOptionalClientScopes() {
return optionalClientScopes;
}
public void setOptionalClientScopes(List<String> optionalClientScopes) {
this.optionalClientScopes = optionalClientScopes;
}
public ResourceServerRepresentation getAuthorizationSettings() {

View file

@ -0,0 +1,87 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.representations.idm;
import java.util.List;
import java.util.Map;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
@JsonIgnoreProperties(ignoreUnknown=true) // Backwards compatibility of admin REST endpoints (ClientTemplateRepresentation was more rich)
public class ClientScopeRepresentation {
protected String id;
protected String name;
protected String description;
protected String protocol;
protected Map<String, String> attributes;
protected List<ProtocolMapperRepresentation> protocolMappers;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public List<ProtocolMapperRepresentation> getProtocolMappers() {
return protocolMappers;
}
public void setProtocolMappers(List<ProtocolMapperRepresentation> protocolMappers) {
this.protocolMappers = protocolMappers;
}
public String getProtocol() {
return protocol;
}
public void setProtocol(String protocol) {
this.protocol = protocol;
}
public Map<String, String> getAttributes() {
return attributes;
}
public void setAttributes(Map<String, String> attributes) {
this.attributes = attributes;
}
}

View file

@ -24,6 +24,7 @@ import java.util.Map;
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
@Deprecated // Use ClientScopeRepresentation instead
public class ClientTemplateRepresentation {
/**
* Use this value in ClientRepresentation.setClientTemplate when you want to clear this value
@ -167,3 +168,4 @@ public class ClientTemplateRepresentation {
this.attributes = attributes;
}
}

View file

@ -29,7 +29,11 @@ public class ProtocolMapperRepresentation {
protected String name;
protected String protocol;
protected String protocolMapper;
@Deprecated // backwards compatibility only
protected boolean consentRequired;
@Deprecated // backwards compatibility only
protected String consentText;
protected Map<String, String> config = new HashMap<String, String>();
@ -74,19 +78,14 @@ public class ProtocolMapperRepresentation {
this.config = config;
}
@Deprecated
public boolean isConsentRequired() {
return consentRequired;
}
public void setConsentRequired(boolean consentRequired) {
this.consentRequired = consentRequired;
}
@Deprecated
public String getConsentText() {
return consentText;
}
public void setConsentText(String consentText) {
this.consentText = consentText;
}
}

View file

@ -106,7 +106,9 @@ public class RealmRepresentation {
protected List<ScopeMappingRepresentation> scopeMappings;
protected Map<String, List<ScopeMappingRepresentation>> clientScopeMappings;
protected List<ClientRepresentation> clients;
protected List<ClientTemplateRepresentation> clientTemplates;
protected List<ClientScopeRepresentation> clientScopes;
protected List<String> defaultDefaultClientScopes;
protected List<String> defaultOptionalClientScopes;
protected Map<String, String> browserSecurityHeaders;
protected Map<String, String> smtpServer;
protected List<UserFederationProviderRepresentation> userFederationProviders;
@ -159,6 +161,8 @@ public class RealmRepresentation {
protected List<ApplicationRepresentation> applications;
@Deprecated
protected List<OAuthClientRepresentation> oauthClients;
@Deprecated
protected List<ClientTemplateRepresentation> clientTemplates;
public String getId() {
return id;
@ -304,9 +308,9 @@ public class RealmRepresentation {
return mapping;
}
public ScopeMappingRepresentation clientTemplateScopeMapping(String clientTemplateName) {
public ScopeMappingRepresentation clientScopeScopeMapping(String clientScopeName) {
ScopeMappingRepresentation mapping = new ScopeMappingRepresentation();
mapping.setClientTemplate(clientTemplateName);
mapping.setClientScope(clientScopeName);
if (scopeMappings == null) scopeMappings = new ArrayList<ScopeMappingRepresentation>();
scopeMappings.add(mapping);
return mapping;
@ -930,12 +934,33 @@ public class RealmRepresentation {
this.groups = groups;
}
@Deprecated // use getClientScopes() instead
public List<ClientTemplateRepresentation> getClientTemplates() {
return clientTemplates;
}
public void setClientTemplates(List<ClientTemplateRepresentation> clientTemplates) {
this.clientTemplates = clientTemplates;
public List<ClientScopeRepresentation> getClientScopes() {
return clientScopes;
}
public void setClientScopes(List<ClientScopeRepresentation> clientScopes) {
this.clientScopes = clientScopes;
}
public List<String> getDefaultDefaultClientScopes() {
return defaultDefaultClientScopes;
}
public void setDefaultDefaultClientScopes(List<String> defaultDefaultClientScopes) {
this.defaultDefaultClientScopes = defaultDefaultClientScopes;
}
public List<String> getDefaultOptionalClientScopes() {
return defaultOptionalClientScopes;
}
public void setDefaultOptionalClientScopes(List<String> defaultOptionalClientScopes) {
this.defaultOptionalClientScopes = defaultOptionalClientScopes;
}
public MultivaluedHashMap<String, ComponentExportRepresentation> getComponents() {

View file

@ -29,6 +29,7 @@ public class RoleRepresentation {
protected String id;
protected String name;
protected String description;
@Deprecated
protected Boolean scopeParamRequired;
protected boolean composite;
protected Composites composites;
@ -96,14 +97,11 @@ public class RoleRepresentation {
this.description = description;
}
@Deprecated
public Boolean isScopeParamRequired() {
return scopeParamRequired;
}
public void setScopeParamRequired(Boolean scopeParamRequired) {
this.scopeParamRequired = scopeParamRequired;
}
public Composites getComposites() {
return composites;
}

View file

@ -27,7 +27,10 @@ import java.util.Set;
public class ScopeMappingRepresentation {
protected String self; // link
protected String client;
@Deprecated // Replaced by clientScope
protected String clientTemplate;
protected String clientScope;
protected Set<String> roles;
public String getSelf() {
@ -46,12 +49,17 @@ public class ScopeMappingRepresentation {
this.client = client;
}
@Deprecated
public String getClientTemplate() {
return clientTemplate;
}
public void setClientTemplate(String clientTemplate) {
this.clientTemplate = clientTemplate;
public String getClientScope() {
return clientScope;
}
public void setClientScope(String clientScope) {
this.clientScope = clientScope;
}
public Set<String> getRoles() {

View file

@ -20,25 +20,25 @@ package org.keycloak.representations.idm;
import java.util.List;
import java.util.Map;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
@JsonIgnoreProperties(ignoreUnknown=true)
public class UserConsentRepresentation {
protected String clientId;
// Key is protocol, Value is list of granted consents for this protocol
protected Map<String, List<String>> grantedProtocolMappers;
protected List<String> grantedRealmRoles;
// Key is clientId, Value is list of granted roles of this client
protected Map<String, List<String>> grantedClientRoles;
protected List<String> grantedClientScopes;
private Long createdDate;
private Long lastUpdatedDate;
@Deprecated
protected List<String> grantedRealmRoles;
public String getClientId() {
return clientId;
}
@ -47,28 +47,12 @@ public class UserConsentRepresentation {
this.clientId = clientId;
}
public Map<String, List<String>> getGrantedProtocolMappers() {
return grantedProtocolMappers;
public List<String> getGrantedClientScopes() {
return grantedClientScopes;
}
public void setGrantedProtocolMappers(Map<String, List<String>> grantedProtocolMappers) {
this.grantedProtocolMappers = grantedProtocolMappers;
}
public List<String> getGrantedRealmRoles() {
return grantedRealmRoles;
}
public void setGrantedRealmRoles(List<String> grantedRealmRoles) {
this.grantedRealmRoles = grantedRealmRoles;
}
public Map<String, List<String>> getGrantedClientRoles() {
return grantedClientRoles;
}
public void setGrantedClientRoles(Map<String, List<String>> grantedClientRoles) {
this.grantedClientRoles = grantedClientRoles;
public void setGrantedClientScopes(List<String> grantedClientScopes) {
this.grantedClientScopes = grantedClientScopes;
}
public void setCreatedDate(Long createdDate) {
@ -86,4 +70,9 @@ public class UserConsentRepresentation {
public Long getLastUpdatedDate() {
return lastUpdatedDate;
}
@Deprecated
public List<String> getGrantedRealmRoles() {
return grantedRealmRoles;
}
}

View file

@ -48,6 +48,8 @@ public class TokenUtil {
public static String attachOIDCScope(String scopeParam) {
if (scopeParam == null || scopeParam.isEmpty()) {
return OAuth2Constants.SCOPE_OPENID;
} else if (hasScope(scopeParam, OAuth2Constants.SCOPE_OPENID)) {
return scopeParam;
} else {
return OAuth2Constants.SCOPE_OPENID + " " + scopeParam;
}

View file

@ -28,8 +28,6 @@
"protocolMapper" : "oidc-usermodel-property-mapper",
"protocol" : "openid-connect",
"name" : "username",
"consentText" : "username",
"consentRequired" : true,
"config" : {
"Claim JSON Type" : "String",
"user.attribute" : "username",
@ -42,8 +40,6 @@
"protocolMapper" : "oidc-usersessionmodel-note-mapper",
"protocol" : "openid-connect",
"name" : "gss delegation credential",
"consentText" : "gss delegation credential",
"consentRequired" : true,
"config" : {
"user.session.note" : "gss_delegation_credential",
"claim.name" : "gss_delegation_credential",

View file

@ -27,8 +27,6 @@
"protocolMapper" : "oidc-usermodel-property-mapper",
"protocol" : "openid-connect",
"name" : "username",
"consentText" : "${username}",
"consentRequired" : true,
"config" : {
"Claim JSON Type" : "String",
"user.attribute" : "username",
@ -41,8 +39,6 @@
"protocolMapper" : "oidc-full-name-mapper",
"protocol" : "openid-connect",
"name" : "full name",
"consentText" : "${fullName}",
"consentRequired" : true,
"config" : {
"id.token.claim" : "true",
"access.token.claim" : "true"
@ -52,8 +48,6 @@
"protocolMapper" : "oidc-usermodel-property-mapper",
"protocol" : "openid-connect",
"name" : "given name",
"consentText" : "${givenName}",
"consentRequired" : true,
"config" : {
"Claim JSON Type" : "String",
"user.attribute" : "firstName",
@ -66,8 +60,6 @@
"protocolMapper" : "oidc-usermodel-property-mapper",
"protocol" : "openid-connect",
"name" : "family name",
"consentText" : "${familyName}",
"consentRequired" : true,
"config" : {
"Claim JSON Type" : "String",
"user.attribute" : "lastName",
@ -80,8 +72,6 @@
"protocolMapper" : "oidc-usermodel-property-mapper",
"protocol" : "openid-connect",
"name" : "email",
"consentText" : "${email}",
"consentRequired" : true,
"config" : {
"Claim JSON Type" : "String",
"user.attribute" : "email",
@ -94,8 +84,6 @@
"protocolMapper" : "oidc-usermodel-attribute-mapper",
"protocol" : "openid-connect",
"name" : "postal code",
"consentText" : "${postal_code}",
"consentRequired" : true,
"config" : {
"Claim JSON Type" : "String",
"user.attribute" : "postal_code",
@ -109,8 +97,6 @@
"protocolMapper" : "oidc-usermodel-attribute-mapper",
"protocol" : "openid-connect",
"name" : "street",
"consentText" : "${street}",
"consentRequired" : true,
"config" : {
"Claim JSON Type" : "String",
"user.attribute" : "street",
@ -124,8 +110,6 @@
"protocolMapper" : "oidc-usermodel-attribute-mapper",
"protocol" : "openid-connect",
"name" : "picture",
"consentText" : "Picture",
"consentRequired" : true,
"config" : {
"Claim JSON Type" : "String",
"user.attribute" : "picture",

View file

@ -20,6 +20,7 @@ package org.keycloak.admin.client.resource;
import org.jboss.resteasy.annotations.cache.NoCache;
import org.keycloak.representations.adapters.action.GlobalRequestResult;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.ClientScopeRepresentation;
import org.keycloak.representations.idm.CredentialRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.representations.idm.UserSessionRepresentation;
@ -122,6 +123,42 @@ public interface ClientResource {
@Path("/roles")
public RolesResource roles();
/**
* Get default client scopes. Only name and ids are returned.
*
* @return default client scopes
*/
@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("default-client-scopes")
List<ClientScopeRepresentation> getDefaultClientScopes();
@PUT
@Path("default-client-scopes/{clientScopeId}")
void addDefaultClientScope(@PathParam("clientScopeId") String clientScopeId);
@DELETE
@Path("default-client-scopes/{clientScopeId}")
void removeDefaultClientScope(@PathParam("clientScopeId") String clientScopeId);
/**
* Get optional client scopes. Only name and ids are returned.
*
* @return optional client scopes
*/
@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("optional-client-scopes")
List<ClientScopeRepresentation> getOptionalClientScopes();
@PUT
@Path("optional-client-scopes/{clientScopeId}")
void addOptionalClientScope(@PathParam("clientScopeId") String clientScopeId);
@DELETE
@Path("optional-client-scopes/{clientScopeId}")
void removeOptionalClientScope(@PathParam("clientScopeId") String clientScopeId);
@Path("/service-account-user")
@GET
@NoCache

View file

@ -17,7 +17,7 @@
package org.keycloak.admin.client.resource;
import org.keycloak.representations.idm.ClientTemplateRepresentation;
import org.keycloak.representations.idm.ClientScopeRepresentation;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
@ -30,7 +30,7 @@ import javax.ws.rs.core.MediaType;
/**
* @author rodrigo.sasaki@icarros.com.br
*/
public interface ClientTemplateResource {
public interface ClientScopeResource {
@Path("protocol-mappers")
public ProtocolMappersResource getProtocolMappers();
@ -40,11 +40,11 @@ public interface ClientTemplateResource {
@GET
@Produces(MediaType.APPLICATION_JSON)
public ClientTemplateRepresentation toRepresentation();
public ClientScopeRepresentation toRepresentation();
@PUT
@Consumes(MediaType.APPLICATION_JSON)
public void update(ClientTemplateRepresentation rep);
public void update(ClientScopeRepresentation rep);
@DELETE
public void remove();

View file

@ -17,7 +17,7 @@
package org.keycloak.admin.client.resource;
import org.keycloak.representations.idm.ClientTemplateRepresentation;
import org.keycloak.representations.idm.ClientScopeRepresentation;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
@ -32,18 +32,18 @@ import java.util.List;
/**
* @author rodrigo.sasaki@icarros.com.br
*/
public interface ClientTemplatesResource {
public interface ClientScopesResource {
@Path("{id}")
public ClientTemplateResource get(@PathParam("id") String id);
ClientScopeResource get(@PathParam("id") String id);
@POST
@Consumes(MediaType.APPLICATION_JSON)
public Response create(ClientTemplateRepresentation clientRepresentation);
public Response create(ClientScopeRepresentation clientScopeRepresentation);
@GET
@Produces(MediaType.APPLICATION_JSON)
public List<ClientTemplateRepresentation> findAll();
public List<ClientScopeRepresentation> findAll();

View file

@ -21,6 +21,7 @@ import org.jboss.resteasy.annotations.cache.NoCache;
import org.keycloak.representations.adapters.action.GlobalRequestResult;
import org.keycloak.representations.idm.AdminEventRepresentation;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.ClientScopeRepresentation;
import org.keycloak.representations.idm.EventRepresentation;
import org.keycloak.representations.idm.GroupRepresentation;
import org.keycloak.representations.idm.PartialImportRepresentation;
@ -39,7 +40,7 @@ import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.IOException;
import java.util.List;
import java.util.Map;
@ -59,8 +60,34 @@ public interface RealmResource {
@Path("clients")
ClientsResource clients();
@Path("client-templates")
ClientTemplatesResource clientTemplates();
@Path("client-scopes")
ClientScopesResource clientScopes();
@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("default-default-client-scopes")
List<ClientScopeRepresentation> getDefaultDefaultClientScopes();
@PUT
@Path("default-default-client-scopes/{clientScopeId}")
void addDefaultDefaultClientScope(@PathParam("clientScopeId") String clientScopeId);
@DELETE
@Path("default-default-client-scopes/{clientScopeId}")
void removeDefaultDefaultClientScope(@PathParam("clientScopeId") String clientScopeId);
@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("default-optional-client-scopes")
List<ClientScopeRepresentation> getDefaultOptionalClientScopes();
@PUT
@Path("default-optional-client-scopes/{clientScopeId}")
void addDefaultOptionalClientScope(@PathParam("clientScopeId") String clientScopeId);
@DELETE
@Path("default-optional-client-scopes/{clientScopeId}")
void removeDefaultOptionalClientScope(@PathParam("clientScopeId") String clientScopeId);
@Path("client-description-converter")
@POST

View file

@ -18,7 +18,7 @@
package org.keycloak.models.cache.infinispan;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientTemplateModel;
import org.keycloak.models.ClientScopeModel;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleContainerModel;
@ -97,60 +97,37 @@ public class ClientAdapter implements ClientModel, CachedObject {
}
@Override
public ClientTemplateModel getClientTemplate() {
if (isUpdated()) return updated.getClientTemplate();
if (cached.getClientTemplate() == null) return null;
return cacheSession.getClientTemplateById(cached.getClientTemplate(), cachedRealm);
}
@Override
public void setClientTemplate(ClientTemplateModel template) {
public void addClientScope(ClientScopeModel clientScope, boolean defaultScope) {
getDelegateForUpdate();
updated.setClientTemplate(template);
updated.addClientScope(clientScope, defaultScope);
}
@Override
public boolean useTemplateScope() {
if (isUpdated()) return updated.useTemplateScope();
return cached.isUseTemplateScope();
}
@Override
public void setUseTemplateScope(boolean value) {
public void removeClientScope(ClientScopeModel clientScope) {
getDelegateForUpdate();
updated.setUseTemplateScope(value);
updated.removeClientScope(clientScope);
}
@Override
public boolean useTemplateConfig() {
if (isUpdated()) return updated.useTemplateConfig();
return cached.isUseTemplateConfig();
public Map<String, ClientScopeModel> getClientScopes(boolean defaultScope, boolean filterByProtocol) {
if (isUpdated()) return updated.getClientScopes(defaultScope, filterByProtocol);
List<String> clientScopeIds = defaultScope ? cached.getDefaultClientScopesIds() : cached.getOptionalClientScopesIds();
// Defaults to openid-connect
String clientProtocol = getProtocol() == null ? "openid-connect" : getProtocol();
Map<String, ClientScopeModel> clientScopes = new HashMap<>();
for (String scopeId : clientScopeIds) {
ClientScopeModel clientScope = cacheSession.getClientScopeById(scopeId, cachedRealm);
if (clientScope != null) {
if (!filterByProtocol || clientScope.getProtocol().equals(clientProtocol)) {
clientScopes.put(clientScope.getName(), clientScope);
}
}
}
return clientScopes;
}
@Override
public void setUseTemplateConfig(boolean value) {
getDelegateForUpdate();
updated.setUseTemplateConfig(value);
}
@Override
public boolean useTemplateMappers() {
if (isUpdated()) 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);

View file

@ -18,12 +18,12 @@
package org.keycloak.models.cache.infinispan;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientTemplateModel;
import org.keycloak.models.ClientScopeModel;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleContainerModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.cache.infinispan.entities.CachedClientTemplate;
import org.keycloak.models.cache.infinispan.entities.CachedClientScope;
import java.util.HashMap;
import java.util.HashSet;
@ -34,14 +34,14 @@ import java.util.Set;
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class ClientTemplateAdapter implements ClientTemplateModel {
public class ClientScopeAdapter implements ClientScopeModel {
protected RealmCacheSession cacheSession;
protected RealmModel cachedRealm;
protected ClientTemplateModel updated;
protected CachedClientTemplate cached;
protected ClientScopeModel updated;
protected CachedClientScope cached;
public ClientTemplateAdapter(RealmModel cachedRealm, CachedClientTemplate cached, RealmCacheSession cacheSession) {
public ClientScopeAdapter(RealmModel cachedRealm, CachedClientScope cached, RealmCacheSession cacheSession) {
this.cachedRealm = cachedRealm;
this.cacheSession = cacheSession;
this.cached = cached;
@ -49,8 +49,8 @@ public class ClientTemplateAdapter implements ClientTemplateModel {
private void getDelegateForUpdate() {
if (updated == null) {
cacheSession.registerClientTemplateInvalidation(cached.getId());
updated = cacheSession.getRealmDelegate().getClientTemplateById(cached.getId(), cachedRealm);
cacheSession.registerClientScopeInvalidation(cached.getId());
updated = cacheSession.getRealmDelegate().getClientScopeById(cached.getId(), cachedRealm);
if (updated == null) throw new IllegalStateException("Not found in database");
}
}
@ -63,7 +63,7 @@ public class ClientTemplateAdapter implements ClientTemplateModel {
protected boolean isUpdated() {
if (updated != null) return true;
if (!invalidated) return false;
updated = cacheSession.getRealmDelegate().getClientTemplateById(cached.getId(), cachedRealm);
updated = cacheSession.getRealmDelegate().getClientScopeById(cached.getId(), cachedRealm);
if (updated == null) throw new IllegalStateException("Not found in database");
return true;
}
@ -157,19 +157,6 @@ public class ClientTemplateAdapter implements ClientTemplateModel {
updated.setProtocol(protocol);
}
@Override
public boolean isFullScopeAllowed() {
if (isUpdated()) return updated.isFullScopeAllowed();
return cached.isFullScopeAllowed();
}
@Override
public void setFullScopeAllowed(boolean value) {
getDelegateForUpdate();
updated.setFullScopeAllowed(value);
}
public Set<RoleModel> getScopeMappings() {
if (isUpdated()) return updated.getScopeMappings();
Set<RoleModel> roles = new HashSet<RoleModel>();
@ -209,7 +196,7 @@ public class ClientTemplateAdapter implements ClientTemplateModel {
@Override
public boolean hasScope(RoleModel role) {
if (isUpdated()) return updated.hasScope(role);
if (cached.isFullScopeAllowed() || cached.getScope().contains(role.getId())) return true;
if (cached.getScope().contains(role.getId())) return true;
Set<RoleModel> roles = getScopeMappings();
@ -219,25 +206,6 @@ public class ClientTemplateAdapter implements ClientTemplateModel {
return false;
}
public boolean isPublicClient() {
if (isUpdated()) return updated.isPublicClient();
return cached.isPublicClient();
}
public void setPublicClient(boolean flag) {
getDelegateForUpdate();
updated.setPublicClient(flag);
}
public boolean isFrontchannelLogout() {
if (isUpdated()) return updated.isPublicClient();
return cached.isFrontchannelLogout();
}
public void setFrontchannelLogout(boolean flag) {
getDelegateForUpdate();
updated.setFrontchannelLogout(flag);
}
@Override
public void setAttribute(String name, String value) {
@ -267,87 +235,13 @@ public class ClientTemplateAdapter implements ClientTemplateModel {
return copy;
}
@Override
public boolean isBearerOnly() {
if (isUpdated()) return updated.isBearerOnly();
return cached.isBearerOnly();
}
@Override
public void setBearerOnly(boolean only) {
getDelegateForUpdate();
updated.setBearerOnly(only);
}
@Override
public boolean isConsentRequired() {
if (isUpdated()) return updated.isConsentRequired();
return cached.isConsentRequired();
}
@Override
public void setConsentRequired(boolean consentRequired) {
getDelegateForUpdate();
updated.setConsentRequired(consentRequired);
}
@Override
public boolean isStandardFlowEnabled() {
if (isUpdated()) return updated.isStandardFlowEnabled();
return cached.isStandardFlowEnabled();
}
@Override
public void setStandardFlowEnabled(boolean standardFlowEnabled) {
getDelegateForUpdate();
updated.setStandardFlowEnabled(standardFlowEnabled);
}
@Override
public boolean isImplicitFlowEnabled() {
if (isUpdated()) return updated.isImplicitFlowEnabled();
return cached.isImplicitFlowEnabled();
}
@Override
public void setImplicitFlowEnabled(boolean implicitFlowEnabled) {
getDelegateForUpdate();
updated.setImplicitFlowEnabled(implicitFlowEnabled);
}
@Override
public boolean isDirectAccessGrantsEnabled() {
if (isUpdated()) return updated.isDirectAccessGrantsEnabled();
return cached.isDirectAccessGrantsEnabled();
}
@Override
public void setDirectAccessGrantsEnabled(boolean directAccessGrantsEnabled) {
getDelegateForUpdate();
updated.setDirectAccessGrantsEnabled(directAccessGrantsEnabled);
}
@Override
public boolean isServiceAccountsEnabled() {
if (isUpdated()) return updated.isServiceAccountsEnabled();
return cached.isServiceAccountsEnabled();
}
@Override
public void setServiceAccountsEnabled(boolean serviceAccountsEnabled) {
getDelegateForUpdate();
updated.setServiceAccountsEnabled(serviceAccountsEnabled);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || !(o instanceof ClientModel)) return false;
ClientTemplateModel that = (ClientTemplateModel) o;
ClientScopeModel that = (ClientScopeModel) o;
return that.getId().equals(getId());
}

View file

@ -1287,15 +1287,15 @@ public class RealmAdapter implements CachedRealmModel {
}
@Override
public List<ClientTemplateModel> getClientTemplates() {
if (isUpdated()) return updated.getClientTemplates();
List<String> clientTemplates = cached.getClientTemplates();
if (clientTemplates.isEmpty()) return Collections.EMPTY_LIST;
List<ClientTemplateModel> apps = new LinkedList<ClientTemplateModel>();
for (String id : clientTemplates) {
ClientTemplateModel model = cacheSession.getClientTemplateById(id, this);
public List<ClientScopeModel> getClientScopes() {
if (isUpdated()) return updated.getClientScopes();
List<String> clientScopes = cached.getClientScopes();
if (clientScopes.isEmpty()) return Collections.EMPTY_LIST;
List<ClientScopeModel> apps = new LinkedList<ClientScopeModel>();
for (String id : clientScopes) {
ClientScopeModel model = cacheSession.getClientScopeById(id, this);
if (model == null) {
throw new IllegalStateException("Cached clientemplate not found: " + id);
throw new IllegalStateException("Cached clientScope not found: " + id);
}
apps.add(model);
}
@ -1304,32 +1304,60 @@ public class RealmAdapter implements CachedRealmModel {
}
@Override
public ClientTemplateModel addClientTemplate(String name) {
public ClientScopeModel addClientScope(String name) {
getDelegateForUpdate();
ClientTemplateModel app = updated.addClientTemplate(name);
cacheSession.registerClientTemplateInvalidation(app.getId());
ClientScopeModel app = updated.addClientScope(name);
cacheSession.registerClientScopeInvalidation(app.getId());
return app;
}
@Override
public ClientTemplateModel addClientTemplate(String id, String name) {
public ClientScopeModel addClientScope(String id, String name) {
getDelegateForUpdate();
ClientTemplateModel app = updated.addClientTemplate(id, name);
cacheSession.registerClientTemplateInvalidation(app.getId());
ClientScopeModel app = updated.addClientScope(id, name);
cacheSession.registerClientScopeInvalidation(app.getId());
return app;
}
@Override
public boolean removeClientTemplate(String id) {
cacheSession.registerClientTemplateInvalidation(id);
public boolean removeClientScope(String id) {
cacheSession.registerClientScopeInvalidation(id);
getDelegateForUpdate();
return updated.removeClientTemplate(id);
return updated.removeClientScope(id);
}
@Override
public ClientTemplateModel getClientTemplateById(String id) {
if (isUpdated()) return updated.getClientTemplateById(id);
return cacheSession.getClientTemplateById(id, this);
public ClientScopeModel getClientScopeById(String id) {
if (isUpdated()) return updated.getClientScopeById(id);
return cacheSession.getClientScopeById(id, this);
}
@Override
public void addDefaultClientScope(ClientScopeModel clientScope, boolean defaultScope) {
getDelegateForUpdate();
updated.addDefaultClientScope(clientScope, defaultScope);
}
@Override
public void removeDefaultClientScope(ClientScopeModel clientScope) {
getDelegateForUpdate();
updated.removeDefaultClientScope(clientScope);
}
@Override
public List<ClientScopeModel> getDefaultClientScopes(boolean defaultScope) {
if (isUpdated()) return updated.getDefaultClientScopes(defaultScope);
List<String> clientScopeIds = defaultScope ? cached.getDefaultDefaultClientScopes() : cached.getOptionalDefaultClientScopes();
List<ClientScopeModel> clientScopes = new LinkedList<>();
for (String scopeId : clientScopeIds) {
ClientScopeModel clientScope = cacheSession.getClientScopeById(scopeId, this);
if (clientScope != null) {
clientScopes.add(clientScope);
}
}
return clientScopes;
}
@Override

View file

@ -27,7 +27,6 @@ import org.keycloak.models.cache.CachedRealmModel;
import org.keycloak.models.cache.infinispan.entities.*;
import org.keycloak.models.cache.infinispan.events.*;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.storage.CacheableStorageProviderModel;
import org.keycloak.storage.StorageId;
import org.keycloak.storage.client.ClientStorageProviderModel;
@ -105,7 +104,7 @@ public class RealmCacheSession implements CacheRealmProvider {
protected Map<String, RealmAdapter> managedRealms = new HashMap<>();
protected Map<String, ClientModel> managedApplications = new HashMap<>();
protected Map<String, ClientTemplateAdapter> managedClientTemplates = new HashMap<>();
protected Map<String, ClientScopeAdapter> managedClientScopes = new HashMap<>();
protected Map<String, RoleAdapter> managedRoles = new HashMap<>();
protected Map<String, GroupAdapter> managedGroups = new HashMap<>();
protected Set<String> listInvalidations = new HashSet<>();
@ -182,16 +181,16 @@ public class RealmCacheSession implements CacheRealmProvider {
}
@Override
public void registerClientTemplateInvalidation(String id) {
invalidateClientTemplate(id);
// Note: Adding/Removing client template is supposed to invalidate CachedRealm as well, so the list of clientTemplates is invalidated.
public void registerClientScopeInvalidation(String id) {
invalidateClientScope(id);
// Note: Adding/Removing client template is supposed to invalidate CachedRealm as well, so the list of clientScopes is invalidated.
// But separate RealmUpdatedEvent will be sent for it. So ClientTemplateEvent don't need to take care of it.
invalidationEvents.add(ClientTemplateEvent.create(id));
}
private void invalidateClientTemplate(String id) {
private void invalidateClientScope(String id) {
invalidations.add(id);
ClientTemplateAdapter adapter = managedClientTemplates.get(id);
ClientScopeAdapter adapter = managedClientScopes.get(id);
if (adapter != null) adapter.invalidate();
}
@ -218,9 +217,9 @@ public class RealmCacheSession implements CacheRealmProvider {
group.invalidate();
continue;
}
ClientTemplateAdapter clientTemplate = managedClientTemplates.get(id);
if (clientTemplate != null) {
clientTemplate.invalidate();
ClientScopeAdapter clientScope = managedClientScopes.get(id);
if (clientScope != null) {
clientScope.invalidate();
continue;
}
RoleAdapter role = managedRoles.get(id);
@ -1134,26 +1133,26 @@ public class RealmCacheSession implements CacheRealmProvider {
}
@Override
public ClientTemplateModel getClientTemplateById(String id, RealmModel realm) {
CachedClientTemplate cached = cache.get(id, CachedClientTemplate.class);
public ClientScopeModel getClientScopeById(String id, RealmModel realm) {
CachedClientScope cached = cache.get(id, CachedClientScope.class);
if (cached != null && !cached.getRealm().equals(realm.getId())) {
cached = null;
}
if (cached == null) {
Long loaded = cache.getCurrentRevision(id);
ClientTemplateModel model = getRealmDelegate().getClientTemplateById(id, realm);
ClientScopeModel model = getRealmDelegate().getClientScopeById(id, realm);
if (model == null) return null;
if (invalidations.contains(id)) return model;
cached = new CachedClientTemplate(loaded, realm, model);
cached = new CachedClientScope(loaded, realm, model);
cache.addRevisioned(cached, startupRevision);
} else if (invalidations.contains(id)) {
return getRealmDelegate().getClientTemplateById(id, realm);
} else if (managedClientTemplates.containsKey(id)) {
return managedClientTemplates.get(id);
return getRealmDelegate().getClientScopeById(id, realm);
} else if (managedClientScopes.containsKey(id)) {
return managedClientScopes.get(id);
}
ClientTemplateAdapter adapter = new ClientTemplateAdapter(realm, cached, this);
managedClientTemplates.put(id, adapter);
ClientScopeAdapter adapter = new ClientScopeAdapter(realm, cached, this);
managedClientScopes.put(id, adapter);
return adapter;
}

View file

@ -88,18 +88,6 @@ public class RoleAdapter implements RoleModel {
updated.setDescription(description);
}
@Override
public boolean isScopeParamRequired() {
if (isUpdated()) return updated.isScopeParamRequired();
return cached.isScopeParamRequired();
}
@Override
public void setScopeParamRequired(boolean scopeParamRequired) {
getDelegateForUpdate();
updated.setScopeParamRequired(scopeParamRequired);
}
@Override
public String getId() {
if (isUpdated()) return updated.getId();

View file

@ -19,6 +19,7 @@ package org.keycloak.models.cache.infinispan;
import org.jboss.logging.Logger;
import org.keycloak.cluster.ClusterProvider;
import org.keycloak.models.ClientScopeModel;
import org.keycloak.models.cache.CachedObject;
import org.keycloak.models.cache.infinispan.events.InvalidationEvent;
import org.keycloak.common.constants.ServiceAccountConstants;
@ -49,6 +50,7 @@ import org.keycloak.models.cache.infinispan.events.UserFederationLinkRemovedEven
import org.keycloak.models.cache.infinispan.events.UserFederationLinkUpdatedEvent;
import org.keycloak.models.cache.infinispan.events.UserFullInvalidationEvent;
import org.keycloak.models.cache.infinispan.events.UserUpdatedEvent;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.models.utils.ReadOnlyUserModelDelegate;
import org.keycloak.storage.CacheableStorageProviderModel;
import org.keycloak.storage.StorageId;
@ -715,15 +717,13 @@ public class UserCacheSession implements UserCache {
consentModel.setCreatedDate(cachedConsent.getCreatedDate());
consentModel.setLastUpdatedDate(cachedConsent.getLastUpdatedDate());
for (String roleId : cachedConsent.getRoleIds()) {
RoleModel role = session.realms().getRoleById(roleId, realm);
if (role != null) {
consentModel.addGrantedRole(role);
for (String clientScopeId : cachedConsent.getClientScopeIds()) {
ClientScopeModel clientScope = KeycloakModelUtils.findClientScopeById(realm, clientScopeId);
if (clientScope != null) {
consentModel.addGrantedClientScope(clientScope);
}
}
for (ProtocolMapperModel protocolMapper : cachedConsent.getProtocolMappers()) {
consentModel.addGrantedProtocolMapper(protocolMapper);
}
return consentModel;
}
@ -852,6 +852,12 @@ public class UserCacheSession implements UserCache {
getDelegate().preRemove(protocolMapper);
}
@Override
public void preRemove(ClientScopeModel clientScope) {
// Not needed to invalidate realm probably. Just consents are affected ATM and they are checked if they exists
getDelegate().preRemove(clientScope);
}
@Override
public void preRemove(RealmModel realm, ComponentModel component) {
if (!component.getProviderType().equals(UserStorageProvider.class.getName()) && !component.getProviderType().equals(ClientStorageProvider.class.getName())) return;

View file

@ -18,6 +18,7 @@
package org.keycloak.models.cache.infinispan.entities;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientScopeModel;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
@ -67,10 +68,8 @@ public class CachedClient extends AbstractRevisioned implements InRealm {
protected boolean serviceAccountsEnabled;
protected int nodeReRegistrationTimeout;
protected Map<String, Integer> registeredNodes;
protected String clientTemplate;
protected boolean useTemplateScope;
protected boolean useTemplateConfig;
protected boolean useTemplateMappers;
protected List<String> defaultClientScopesIds;
protected List<String> optionalClientScopesIds;
public CachedClient(Long revision, RealmModel realm, ClientModel model) {
super(revision, model.getId());
@ -111,12 +110,15 @@ public class CachedClient extends AbstractRevisioned implements InRealm {
nodeReRegistrationTimeout = model.getNodeReRegistrationTimeout();
registeredNodes = new TreeMap<>(model.getRegisteredNodes());
if (model.getClientTemplate() != null) {
clientTemplate = model.getClientTemplate().getId();
defaultClientScopesIds = new LinkedList<>();
for (ClientScopeModel clientScope : model.getClientScopes(true, false).values()) {
defaultClientScopesIds.add(clientScope.getId());
}
optionalClientScopesIds = new LinkedList<>();
for (ClientScopeModel clientScope : model.getClientScopes(false, false).values()) {
optionalClientScopesIds.add(clientScope.getId());
}
useTemplateConfig = model.useTemplateConfig();
useTemplateMappers = model.useTemplateMappers();
useTemplateScope = model.useTemplateScope();
}
public String getClientId() {
@ -243,20 +245,12 @@ public class CachedClient extends AbstractRevisioned implements InRealm {
return registeredNodes;
}
public String getClientTemplate() {
return clientTemplate;
public List<String> getDefaultClientScopesIds() {
return defaultClientScopesIds;
}
public boolean isUseTemplateScope() {
return useTemplateScope;
}
public boolean isUseTemplateConfig() {
return useTemplateConfig;
}
public boolean isUseTemplateMappers() {
return useTemplateMappers;
public List<String> getOptionalClientScopesIds() {
return optionalClientScopesIds;
}
public Map<String, String> getAuthFlowBindings() {

View file

@ -17,7 +17,7 @@
package org.keycloak.models.cache.infinispan.entities;
import org.keycloak.models.ClientTemplateModel;
import org.keycloak.models.ClientScopeModel;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
@ -31,32 +31,22 @@ import java.util.Set;
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class CachedClientTemplate extends AbstractRevisioned implements InRealm {
public class CachedClientScope extends AbstractRevisioned implements InRealm {
private String name;
private String description;
private String realm;
private String protocol;
private boolean fullScopeAllowed;
private boolean publicClient;
private boolean frontchannelLogout;
private boolean bearerOnly;
private boolean consentRequired;
private boolean standardFlowEnabled;
private boolean implicitFlowEnabled;
private boolean directAccessGrantsEnabled;
private boolean serviceAccountsEnabled;
private Set<String> scope = new HashSet<>();
private Set<ProtocolMapperModel> protocolMappers = new HashSet<ProtocolMapperModel>();
private Map<String, String> attributes = new HashMap<>();
public CachedClientTemplate(Long revision, RealmModel realm, ClientTemplateModel model) {
public CachedClientScope(Long revision, RealmModel realm, ClientScopeModel model) {
super(revision, model.getId());
name = model.getName();
description = model.getDescription();
this.realm = realm.getId();
protocol = model.getProtocol();
fullScopeAllowed = model.isFullScopeAllowed();
for (ProtocolMapperModel mapper : model.getProtocolMappers()) {
this.protocolMappers.add(mapper);
}
@ -64,14 +54,6 @@ public class CachedClientTemplate extends AbstractRevisioned implements InRealm
scope.add(role.getId());
}
attributes.putAll(model.getAttributes());
frontchannelLogout = model.isFrontchannelLogout();
publicClient = model.isPublicClient();
bearerOnly = model.isBearerOnly();
consentRequired = model.isConsentRequired();
standardFlowEnabled = model.isStandardFlowEnabled();
implicitFlowEnabled = model.isImplicitFlowEnabled();
directAccessGrantsEnabled = model.isDirectAccessGrantsEnabled();
serviceAccountsEnabled = model.isServiceAccountsEnabled();
}
public String getName() {
@ -93,46 +75,10 @@ public class CachedClientTemplate extends AbstractRevisioned implements InRealm
return protocol;
}
public boolean isFullScopeAllowed() {
return fullScopeAllowed;
}
public Set<String> getScope() {
return scope;
}
public boolean isPublicClient() {
return publicClient;
}
public boolean isFrontchannelLogout() {
return frontchannelLogout;
}
public boolean isBearerOnly() {
return bearerOnly;
}
public boolean isConsentRequired() {
return consentRequired;
}
public boolean isStandardFlowEnabled() {
return standardFlowEnabled;
}
public boolean isImplicitFlowEnabled() {
return implicitFlowEnabled;
}
public boolean isDirectAccessGrantsEnabled() {
return directAccessGrantsEnabled;
}
public boolean isServiceAccountsEnabled() {
return serviceAccountsEnabled;
}
public Map<String, String> getAttributes() {
return attributes;
}

View file

@ -24,7 +24,7 @@ import org.keycloak.models.AuthenticationExecutionModel;
import org.keycloak.models.AuthenticationFlowModel;
import org.keycloak.models.AuthenticatorConfigModel;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientTemplateModel;
import org.keycloak.models.ClientScopeModel;
import org.keycloak.models.GroupModel;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.models.IdentityProviderModel;
@ -135,7 +135,9 @@ public class CachedRealm extends AbstractExtendableRevisioned {
}
protected List<String> defaultGroups = new LinkedList<String>();
protected List<String> clientTemplates= new LinkedList<>();
protected List<String> clientScopes = new LinkedList<>();
protected List<String> defaultDefaultClientScopes = new LinkedList<>();
protected List<String> optionalDefaultClientScopes = new LinkedList<>();
protected boolean internationalizationEnabled;
protected Set<String> supportedLocales;
protected String defaultLocale;
@ -227,7 +229,7 @@ public class CachedRealm extends AbstractExtendableRevisioned {
ClientModel masterAdminClient = model.getMasterAdminClient();
this.masterAdminClient = (masterAdminClient != null) ? masterAdminClient.getId() : null;
cacheClientTemplates(model);
cacheClientScopes(model);
internationalizationEnabled = model.isInternationalizationEnabled();
supportedLocales = model.getSupportedLocales();
@ -279,9 +281,15 @@ public class CachedRealm extends AbstractExtendableRevisioned {
}
protected void cacheClientTemplates(RealmModel model) {
for (ClientTemplateModel template : model.getClientTemplates()) {
clientTemplates.add(template.getId());
protected void cacheClientScopes(RealmModel model) {
for (ClientScopeModel clientScope : model.getClientScopes()) {
clientScopes.add(clientScope.getId());
}
for (ClientScopeModel clientScope : model.getDefaultClientScopes(true)) {
defaultDefaultClientScopes.add(clientScope.getId());
}
for (ClientScopeModel clientScope : model.getDefaultClientScopes(false)) {
optionalDefaultClientScopes.add(clientScope.getId());
}
}
@ -585,8 +593,16 @@ public class CachedRealm extends AbstractExtendableRevisioned {
return defaultGroups;
}
public List<String> getClientTemplates() {
return clientTemplates;
public List<String> getClientScopes() {
return clientScopes;
}
public List<String> getDefaultDefaultClientScopes() {
return defaultDefaultClientScopes;
}
public List<String> getOptionalDefaultClientScopes() {
return optionalDefaultClientScopes;
}
public List<AuthenticationFlowModel> getAuthenticationFlowList() {

View file

@ -32,7 +32,6 @@ public class CachedRole extends AbstractRevisioned implements InRealm {
final protected String name;
final protected String realm;
final protected String description;
final protected Boolean scopeParamRequired;
final protected boolean composite;
final protected Set<String> composites = new HashSet<String>();
@ -41,7 +40,6 @@ public class CachedRole extends AbstractRevisioned implements InRealm {
composite = model.isComposite();
description = model.getDescription();
name = model.getName();
scopeParamRequired = model.isScopeParamRequired();
this.realm = realm.getId();
if (composite) {
for (RoleModel child : model.getComposites()) {
@ -63,10 +61,6 @@ public class CachedRole extends AbstractRevisioned implements InRealm {
return description;
}
public Boolean isScopeParamRequired() {
return scopeParamRequired;
}
public boolean isComposite() {
return composite;
}

View file

@ -17,6 +17,7 @@
package org.keycloak.models.cache.infinispan.entities;
import org.keycloak.models.ClientScopeModel;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserConsentModel;
@ -30,16 +31,14 @@ import java.util.Set;
public class CachedUserConsent {
private final String clientDbId;
private final Set<ProtocolMapperModel> protocolMappers = new HashSet<>();
private final Set<String> roleIds = new HashSet<>();
private final Set<String> clientScopeIds = new HashSet<>();
private final Long createdDate;
private final Long lastUpdatedDate;
public CachedUserConsent(UserConsentModel consentModel) {
this.clientDbId = consentModel.getClient().getId();
this.protocolMappers.addAll(consentModel.getGrantedProtocolMappers());
for (RoleModel role : consentModel.getGrantedRoles()) {
this.roleIds.add(role.getId());
for (ClientScopeModel clientScope : consentModel.getGrantedClientScopes()) {
this.clientScopeIds.add(clientScope.getId());
}
this.createdDate = consentModel.getCreatedDate();
this.lastUpdatedDate = consentModel.getLastUpdatedDate();
@ -49,12 +48,8 @@ public class CachedUserConsent {
return clientDbId;
}
public Set<ProtocolMapperModel> getProtocolMappers() {
return protocolMappers;
}
public Set<String> getRoleIds() {
return roleIds;
public Set<String> getClientScopeIds() {
return clientScopeIds;
}
public Long getCreatedDate() {

View file

@ -28,6 +28,9 @@ import org.infinispan.commons.marshall.MarshallUtil;
import org.infinispan.commons.marshall.SerializeWith;
/**
* TODO Leave the name ClientTemplateEvent just due the backwards compatibility of infinispan migration. See if can be renamed based on
* rolling upgrades plan...
*
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
@SerializeWith(ClientTemplateEvent.ExternalizerImpl.class)

View file

@ -1,7 +1,7 @@
package org.keycloak.models.cache.infinispan.stream;
import org.keycloak.models.cache.infinispan.entities.CachedClient;
import org.keycloak.models.cache.infinispan.entities.CachedClientTemplate;
import org.keycloak.models.cache.infinispan.entities.CachedClientScope;
import org.keycloak.models.cache.infinispan.entities.CachedGroup;
import org.keycloak.models.cache.infinispan.entities.CachedRole;
import org.keycloak.models.cache.infinispan.entities.Revisioned;
@ -55,9 +55,9 @@ public class HasRolePredicate implements Predicate<Map.Entry<String, Revisioned>
if (cachedClient.getScope().contains(role)) return true;
}
if (value instanceof CachedClientTemplate) {
CachedClientTemplate cachedClientTemplate = (CachedClientTemplate)value;
if (cachedClientTemplate.getScope().contains(role)) return true;
if (value instanceof CachedClientScope) {
CachedClientScope cachedClientScope = (CachedClientScope)value;
if (cachedClientScope.getScope().contains(role)) return true;
}
return false;

View file

@ -238,44 +238,6 @@ public class AuthenticatedClientSessionAdapter implements AuthenticatedClientSes
update(task);
}
@Override
public Set<String> getRoles() {
return entity.getRoles();
}
@Override
public void setRoles(Set<String> roles) {
ClientSessionUpdateTask task = new ClientSessionUpdateTask() {
@Override
public void runUpdate(AuthenticatedClientSessionEntity entity) {
entity.setRoles(roles); // TODO not thread-safe. But we will remove setRoles anyway...?
}
};
update(task);
}
@Override
public Set<String> getProtocolMappers() {
return entity.getProtocolMappers();
}
@Override
public void setProtocolMappers(Set<String> protocolMappers) {
ClientSessionUpdateTask task = new ClientSessionUpdateTask() {
@Override
public void runUpdate(AuthenticatedClientSessionEntity entity) {
entity.setProtocolMappers(protocolMappers); // TODO not thread-safe. But we will remove setProtocolMappers anyway...?
}
};
update(task);
}
@Override
public String getNote(String name) {
return entity.getNotes().get(name);

View file

@ -99,26 +99,14 @@ public class AuthenticationSessionAdapter implements AuthenticationSessionModel
}
@Override
public Set<String> getRoles() {
if (entity.getRoles() == null || entity.getRoles().isEmpty()) return Collections.emptySet();
return new HashSet<>(entity.getRoles());
public Set<String> getClientScopes() {
if (entity.getClientScopes() == null || entity.getClientScopes().isEmpty()) return Collections.emptySet();
return new HashSet<>(entity.getClientScopes());
}
@Override
public void setRoles(Set<String> roles) {
entity.setRoles(roles);
update();
}
@Override
public Set<String> getProtocolMappers() {
if (entity.getProtocolMappers() == null || entity.getProtocolMappers().isEmpty()) return Collections.emptySet();
return new HashSet<>(entity.getProtocolMappers());
}
@Override
public void setProtocolMappers(Set<String> protocolMappers) {
entity.setProtocolMappers(protocolMappers);
public void setClientScopes(Set<String> clientScopes) {
entity.setClientScopes(clientScopes);
update();
}

View file

@ -925,9 +925,7 @@ public class InfinispanUserSessionProvider implements UserSessionProvider {
entity.setAuthMethod(clientSession.getProtocol());
entity.setNotes(clientSession.getNotes() == null ? new ConcurrentHashMap<>() : clientSession.getNotes());
entity.setProtocolMappers(clientSession.getProtocolMappers());
entity.setRedirectUri(clientSession.getRedirectUri());
entity.setRoles(clientSession.getRoles());
entity.setTimestamp(clientSession.getTimestamp());
SessionUpdateTask<AuthenticatedClientSessionEntity> createClientSessionTask = Tasks.addIfAbsentSync();

View file

@ -41,7 +41,6 @@ import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>

View file

@ -21,7 +21,6 @@ import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.infinispan.commons.marshall.Externalizer;
@ -49,8 +48,6 @@ public class AuthenticatedClientSessionEntity extends SessionEntity {
private volatile int timestamp;
private String action;
private Set<String> roles;
private Set<String> protocolMappers;
private Map<String, String> notes = new ConcurrentHashMap<>();
private String currentRefreshToken;
@ -94,22 +91,6 @@ public class AuthenticatedClientSessionEntity extends SessionEntity {
this.action = action;
}
public Set<String> getRoles() {
return roles;
}
public void setRoles(Set<String> roles) {
this.roles = roles;
}
public Set<String> getProtocolMappers() {
return protocolMappers;
}
public void setProtocolMappers(Set<String> protocolMappers) {
this.protocolMappers = protocolMappers;
}
public Map<String, String> getNotes() {
return notes;
}
@ -199,9 +180,6 @@ public class AuthenticatedClientSessionEntity extends SessionEntity {
Map<String, String> notes = session.getNotes();
KeycloakMarshallUtil.writeMap(notes, KeycloakMarshallUtil.STRING_EXT, KeycloakMarshallUtil.STRING_EXT, output);
KeycloakMarshallUtil.writeCollection(session.getProtocolMappers(), KeycloakMarshallUtil.STRING_EXT, output);
KeycloakMarshallUtil.writeCollection(session.getRoles(), KeycloakMarshallUtil.STRING_EXT, output);
MarshallUtil.marshallString(session.getCurrentRefreshToken(), output);
MarshallUtil.marshallInt(output, session.getCurrentRefreshTokenUseCount());
}
@ -222,12 +200,6 @@ public class AuthenticatedClientSessionEntity extends SessionEntity {
new KeycloakMarshallUtil.ConcurrentHashMapBuilder<>());
sessionEntity.setNotes(notes);
Set<String> protocolMappers = KeycloakMarshallUtil.readCollection(input, KeycloakMarshallUtil.STRING_EXT, new KeycloakMarshallUtil.HashSetBuilder<>());
sessionEntity.setProtocolMappers(protocolMappers);
Set<String> roles = KeycloakMarshallUtil.readCollection(input, KeycloakMarshallUtil.STRING_EXT, new KeycloakMarshallUtil.HashSetBuilder<>());
sessionEntity.setRoles(roles);
sessionEntity.setCurrentRefreshToken(MarshallUtil.unmarshallString(input));
sessionEntity.setCurrentRefreshTokenUseCount(MarshallUtil.unmarshallInt(input));

View file

@ -45,8 +45,7 @@ public class AuthenticationSessionEntity implements Serializable {
private String redirectUri;
private String action;
private Set<String> roles;
private Set<String> protocolMappers;
private Set<String> clientScopes;
private Map<String, AuthenticationSessionModel.ExecutionStatus> executionStatus = new ConcurrentHashMap<>();
private String protocol;
@ -62,7 +61,7 @@ public class AuthenticationSessionEntity implements Serializable {
public AuthenticationSessionEntity(
String clientUUID,
String authUserId,
String redirectUri, String action, Set<String> roles, Set<String> protocolMappers,
String redirectUri, String action, Set<String> clientScopes,
Map<String, AuthenticationSessionModel.ExecutionStatus> executionStatus, String protocol,
Map<String, String> clientNotes, Map<String, String> authNotes, Set<String> requiredActions, Map<String, String> userSessionNotes) {
this.clientUUID = clientUUID;
@ -71,8 +70,7 @@ public class AuthenticationSessionEntity implements Serializable {
this.redirectUri = redirectUri;
this.action = action;
this.roles = roles;
this.protocolMappers = protocolMappers;
this.clientScopes = clientScopes;
this.executionStatus = executionStatus;
this.protocol = protocol;
@ -115,20 +113,12 @@ public class AuthenticationSessionEntity implements Serializable {
this.action = action;
}
public Set<String> getRoles() {
return roles;
public Set<String> getClientScopes() {
return clientScopes;
}
public void setRoles(Set<String> roles) {
this.roles = roles;
}
public Set<String> getProtocolMappers() {
return protocolMappers;
}
public void setProtocolMappers(Set<String> protocolMappers) {
this.protocolMappers = protocolMappers;
public void setClientScopes(Set<String> clientScopes) {
this.clientScopes = clientScopes;
}
public Map<String, AuthenticationSessionModel.ExecutionStatus> getExecutionStatus() {
@ -215,8 +205,7 @@ public class AuthenticationSessionEntity implements Serializable {
MarshallUtil.marshallString(value.redirectUri, output);
MarshallUtil.marshallString(value.action, output);
KeycloakMarshallUtil.writeCollection(value.roles, KeycloakMarshallUtil.STRING_EXT, output);
KeycloakMarshallUtil.writeCollection(value.protocolMappers, KeycloakMarshallUtil.STRING_EXT, output);
KeycloakMarshallUtil.writeCollection(value.clientScopes, KeycloakMarshallUtil.STRING_EXT, output);
KeycloakMarshallUtil.writeMap(value.executionStatus, KeycloakMarshallUtil.STRING_EXT, EXECUTION_STATUS_EXT, output);
MarshallUtil.marshallString(value.protocol, output);
@ -245,8 +234,7 @@ public class AuthenticationSessionEntity implements Serializable {
MarshallUtil.unmarshallString(input), // redirectUri
MarshallUtil.unmarshallString(input), // action
KeycloakMarshallUtil.readCollection(input, KeycloakMarshallUtil.STRING_EXT, size -> new ConcurrentHashSet<>()), // roles
KeycloakMarshallUtil.readCollection(input, KeycloakMarshallUtil.STRING_EXT, size -> new ConcurrentHashSet<>()), // protocolMappers
KeycloakMarshallUtil.readCollection(input, KeycloakMarshallUtil.STRING_EXT, size -> new ConcurrentHashSet<>()), // clientScopes
KeycloakMarshallUtil.readMap(input, KeycloakMarshallUtil.STRING_EXT, EXECUTION_STATUS_EXT, size -> new ConcurrentHashMap<>(size)), // executionStatus
MarshallUtil.unmarshallString(input), // protocol

View file

@ -178,8 +178,6 @@ public class ConcurrencyJDGRemoveSessionTest {
clientSession.setAuthMethod("saml");
clientSession.setAction("something");
clientSession.setTimestamp(1234);
clientSession.setProtocolMappers(new HashSet<>(Arrays.asList("mapper1", "mapper2")));
clientSession.setRoles(new HashSet<>(Arrays.asList("role1", "role2")));
session.getAuthenticatedClientSessions().put(CLIENT_1_UUID.toString(), clientSession.getId());
SessionEntityWrapper<UserSessionEntity> wrappedSession = new SessionEntityWrapper<>(session);

View file

@ -18,8 +18,6 @@
package org.keycloak.cluster.infinispan;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@ -97,8 +95,6 @@ public class ConcurrencyJDGSessionsCacheTest {
clientSession.setAuthMethod("saml");
clientSession.setAction("something");
clientSession.setTimestamp(1234);
clientSession.setProtocolMappers(new HashSet<>(Arrays.asList("mapper1", "mapper2")));
clientSession.setRoles(new HashSet<>(Arrays.asList("role1", "role2")));
session.getAuthenticatedClientSessions().put(CLIENT_1_UUID.toString(), clientSession.getId());
SessionEntityWrapper<UserSessionEntity> wrappedSession = new SessionEntityWrapper<>(session);

View file

@ -75,8 +75,6 @@ public class DistributedCacheConcurrentWritesTest {
clientSession.setAuthMethod("saml");
clientSession.setAction("something");
clientSession.setTimestamp(1234);
clientSession.setProtocolMappers(new HashSet<>(Arrays.asList("mapper1", "mapper2")));
clientSession.setRoles(new HashSet<>(Arrays.asList("role1", "role2")));
session.getAuthenticatedClientSessions().put(CLIENT_1_UUID.toString(), clientSession.getId());
cache1.put("123", session);

View file

@ -17,8 +17,6 @@
package org.keycloak.models.sessions.infinispan.initializer;
import java.util.Arrays;
import java.util.HashSet;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
@ -75,8 +73,6 @@ public class DistributedCacheWriteSkewTest {
clientSession.setAuthMethod("saml");
clientSession.setAction("something");
clientSession.setTimestamp(1234);
clientSession.setProtocolMappers(new HashSet<>(Arrays.asList("mapper1", "mapper2")));
clientSession.setRoles(new HashSet<>(Arrays.asList("role1", "role2")));
session.getAuthenticatedClientSessions().put(CLIENT_1_UUID.toString(), clientSession.getId());
cache1.put("123", session);

View file

@ -327,8 +327,7 @@ public class JpaUpdate1_2_0_Beta1 extends CustomKeycloakTask {
.addColumnValue("ID", mapperId)
.addColumnValue("PROTOCOL", protocolMapper.getProtocol())
.addColumnValue("NAME", protocolMapper.getName())
.addColumnValue("CONSENT_REQUIRED", protocolMapper.isConsentRequired())
.addColumnValue("CONSENT_TEXT", protocolMapper.getConsentText())
.addColumnValue("CONSENT_REQUIRED", false)
.addColumnValue("PROTOCOL_MAPPER_NAME", protocolMapper.getProtocolMapper())
.addColumnValue("CLIENT_ID", resultSet.getString("ID"));
statements.add(insert);

View file

@ -18,20 +18,27 @@
package org.keycloak.models.jpa;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientTemplateModel;
import org.keycloak.models.ClientScopeModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ModelDuplicateException;
import org.keycloak.models.ModelException;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleContainerModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.jpa.entities.ClientEntity;
import org.keycloak.models.jpa.entities.ClientTemplateEntity;
import org.keycloak.models.jpa.entities.ClientScopeClientMappingEntity;
import org.keycloak.models.jpa.entities.ClientScopeEntity;
import org.keycloak.models.jpa.entities.ClientScopeRoleMappingEntity;
import org.keycloak.models.jpa.entities.ProtocolMapperEntity;
import org.keycloak.models.jpa.entities.RoleEntity;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
import org.keycloak.protocol.oidc.OIDCLoginProtocolFactory;
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Collection;
@ -317,56 +324,48 @@ public class ClientAdapter implements ClientModel, JpaModel<ClientEntity> {
}
@Override
public ClientTemplateModel getClientTemplate() {
ClientTemplateEntity templateEntity = entity.getClientTemplate();
if (templateEntity == null) return null;
return session.realms().getClientTemplateById(templateEntity.getId(), realm);
public void addClientScope(ClientScopeModel clientScope, boolean defaultScope) {
if (getClientScopes(defaultScope, false).containsKey(clientScope.getName())) return;
ClientScopeClientMappingEntity entity = new ClientScopeClientMappingEntity();
entity.setClientScope(ClientScopeAdapter.toClientScopeEntity(clientScope, em));
entity.setClient(getEntity());
entity.setDefaultScope(defaultScope);
em.persist(entity);
em.flush();
em.detach(entity);
}
@Override
public void setClientTemplate(ClientTemplateModel template) {
if (template == null) {
entity.setClientTemplate(null);
public void removeClientScope(ClientScopeModel clientScope) {
int numRemoved = em.createNamedQuery("deleteClientScopeClientMapping")
.setParameter("clientScope", ClientScopeAdapter.toClientScopeEntity(clientScope, em))
.setParameter("client", getEntity())
.executeUpdate();
em.flush();
}
} else {
ClientTemplateEntity templateEntity = em.getReference(ClientTemplateEntity.class, template.getId());
entity.setClientTemplate(templateEntity);
@Override
public Map<String, ClientScopeModel> getClientScopes(boolean defaultScope, boolean filterByProtocol) {
TypedQuery<String> query = em.createNamedQuery("clientScopeClientMappingIdsByClient", String.class);
query.setParameter("client", getEntity());
query.setParameter("defaultScope", defaultScope);
List<String> ids = query.getResultList();
// Defaults to openid-connect
String clientProtocol = getProtocol() == null ? OIDCLoginProtocol.LOGIN_PROTOCOL : getProtocol();
Map<String, ClientScopeModel> clientScopes = new HashMap<>();
for (String clientScopeId : ids) {
ClientScopeModel clientScope = realm.getClientScopeById(clientScopeId);
if (clientScope == null) continue;
if (!filterByProtocol || clientScope.getProtocol().equals(clientProtocol)) {
clientScopes.put(clientScope.getName(), clientScope);
}
}
return clientScopes;
}
@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) {
@ -384,8 +383,6 @@ public class ClientAdapter implements ClientModel, JpaModel<ClientEntity> {
mapping.setName(entity.getName());
mapping.setProtocol(entity.getProtocol());
mapping.setProtocolMapper(entity.getProtocolMapper());
mapping.setConsentRequired(entity.isConsentRequired());
mapping.setConsentText(entity.getConsentText());
Map<String, String> config = new HashMap<String, String>();
if (entity.getConfig() != null) {
config.putAll(entity.getConfig());
@ -409,8 +406,6 @@ public class ClientAdapter implements ClientModel, JpaModel<ClientEntity> {
entity.setProtocolMapper(model.getProtocolMapper());
entity.setClient(this.entity);
entity.setConfig(model.getConfig());
entity.setConsentRequired(model.isConsentRequired());
entity.setConsentText(model.getConsentText());
em.persist(entity);
this.entity.getProtocolMappers().add(entity);
@ -453,8 +448,6 @@ public class ClientAdapter implements ClientModel, JpaModel<ClientEntity> {
public void updateProtocolMapper(ProtocolMapperModel mapping) {
ProtocolMapperEntity entity = getProtocolMapperEntity(mapping.getId());
entity.setProtocolMapper(mapping.getProtocolMapper());
entity.setConsentRequired(mapping.isConsentRequired());
entity.setConsentText(mapping.getConsentText());
if (entity.getConfig() == null) {
entity.setConfig(mapping.getConfig());
} else {
@ -485,8 +478,6 @@ public class ClientAdapter implements ClientModel, JpaModel<ClientEntity> {
mapping.setName(entity.getName());
mapping.setProtocol(entity.getProtocol());
mapping.setProtocolMapper(entity.getProtocolMapper());
mapping.setConsentRequired(entity.isConsentRequired());
mapping.setConsentText(entity.getConsentText());
Map<String, String> config = new HashMap<String, String>();
if (entity.getConfig() != null) config.putAll(entity.getConfig());
mapping.setConfig(config);

View file

@ -17,17 +17,17 @@
package org.keycloak.models.jpa;
import org.keycloak.models.ClientTemplateModel;
import org.keycloak.models.ClientScopeModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ModelDuplicateException;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleContainerModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.jpa.entities.ClientTemplateEntity;
import org.keycloak.models.jpa.entities.ClientScopeEntity;
import org.keycloak.models.jpa.entities.ClientScopeRoleMappingEntity;
import org.keycloak.models.jpa.entities.ProtocolMapperEntity;
import org.keycloak.models.jpa.entities.RoleEntity;
import org.keycloak.models.jpa.entities.TemplateScopeMappingEntity;
import org.keycloak.models.utils.KeycloakModelUtils;
import javax.persistence.EntityManager;
@ -42,21 +42,21 @@ import java.util.Set;
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class ClientTemplateAdapter implements ClientTemplateModel , JpaModel<ClientTemplateEntity> {
public class ClientScopeAdapter implements ClientScopeModel, JpaModel<ClientScopeEntity> {
protected KeycloakSession session;
protected RealmModel realm;
protected EntityManager em;
protected ClientTemplateEntity entity;
protected ClientScopeEntity entity;
public ClientTemplateAdapter(RealmModel realm, EntityManager em, KeycloakSession session, ClientTemplateEntity entity) {
public ClientScopeAdapter(RealmModel realm, EntityManager em, KeycloakSession session, ClientScopeEntity entity) {
this.session = session;
this.realm = realm;
this.em = em;
this.entity = entity;
}
public ClientTemplateEntity getEntity() {
public ClientScopeEntity getEntity() {
return entity;
}
@ -77,6 +77,7 @@ public class ClientTemplateAdapter implements ClientTemplateModel , JpaModel<Cli
@Override
public void setName(String name) {
name = KeycloakModelUtils.convertClientScopeName(name);
entity.setName(name);
}
@ -106,8 +107,6 @@ public class ClientTemplateAdapter implements ClientTemplateModel , JpaModel<Cli
mapping.setName(entity.getName());
mapping.setProtocol(entity.getProtocol());
mapping.setProtocolMapper(entity.getProtocolMapper());
mapping.setConsentRequired(entity.isConsentRequired());
mapping.setConsentText(entity.getConsentText());
Map<String, String> config = new HashMap<String, String>();
if (entity.getConfig() != null) {
config.putAll(entity.getConfig());
@ -129,10 +128,8 @@ public class ClientTemplateAdapter implements ClientTemplateModel , JpaModel<Cli
entity.setName(model.getName());
entity.setProtocol(model.getProtocol());
entity.setProtocolMapper(model.getProtocolMapper());
entity.setClientTemplate(this.entity);
entity.setClientScope(this.entity);
entity.setConfig(model.getConfig());
entity.setConsentRequired(model.isConsentRequired());
entity.setConsentText(model.getConsentText());
em.persist(entity);
this.entity.getProtocolMappers().add(entity);
@ -175,8 +172,6 @@ public class ClientTemplateAdapter implements ClientTemplateModel , JpaModel<Cli
public void updateProtocolMapper(ProtocolMapperModel mapping) {
ProtocolMapperEntity entity = getProtocolMapperEntity(mapping.getId());
entity.setProtocolMapper(mapping.getProtocolMapper());
entity.setConsentRequired(mapping.isConsentRequired());
entity.setConsentText(mapping.getConsentText());
if (entity.getConfig() == null) {
entity.setConfig(mapping.getConfig());
} else {
@ -207,24 +202,12 @@ public class ClientTemplateAdapter implements ClientTemplateModel , JpaModel<Cli
mapping.setName(entity.getName());
mapping.setProtocol(entity.getProtocol());
mapping.setProtocolMapper(entity.getProtocolMapper());
mapping.setConsentRequired(entity.isConsentRequired());
mapping.setConsentText(entity.getConsentText());
Map<String, String> config = new HashMap<String, String>();
if (entity.getConfig() != null) config.putAll(entity.getConfig());
mapping.setConfig(config);
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();
@ -233,7 +216,7 @@ public class ClientTemplateAdapter implements ClientTemplateModel , JpaModel<Cli
for (RoleModel role : roleMappings) {
RoleContainerModel container = role.getContainer();
if (container instanceof RealmModel) {
if (((RealmModel) container).getId().equals(realm.getId())) {
if (container.getId().equals(realm.getId())) {
appRoles.add(role);
}
}
@ -244,8 +227,8 @@ public class ClientTemplateAdapter implements ClientTemplateModel , JpaModel<Cli
@Override
public Set<RoleModel> getScopeMappings() {
TypedQuery<String> query = em.createNamedQuery("clientTemplateScopeMappingIds", String.class);
query.setParameter("template", getEntity());
TypedQuery<String> query = em.createNamedQuery("clientScopeRoleMappingIds", String.class);
query.setParameter("clientScope", getEntity());
List<String> ids = query.getResultList();
Set<RoleModel> roles = new HashSet<RoleModel>();
for (String roleId : ids) {
@ -259,8 +242,8 @@ public class ClientTemplateAdapter implements ClientTemplateModel , JpaModel<Cli
@Override
public void addScopeMapping(RoleModel role) {
if (hasScope(role)) return;
TemplateScopeMappingEntity entity = new TemplateScopeMappingEntity();
entity.setTemplate(getEntity());
ClientScopeRoleMappingEntity entity = new ClientScopeRoleMappingEntity();
entity.setClientScope(getEntity());
RoleEntity roleEntity = RoleAdapter.toRoleEntity(role, em);
entity.setRole(roleEntity);
em.persist(entity);
@ -270,17 +253,17 @@ public class ClientTemplateAdapter implements ClientTemplateModel , JpaModel<Cli
@Override
public void deleteScopeMapping(RoleModel role) {
TypedQuery<TemplateScopeMappingEntity> query = getRealmScopeMappingQuery(role);
List<TemplateScopeMappingEntity> results = query.getResultList();
TypedQuery<ClientScopeRoleMappingEntity> query = getRealmScopeMappingQuery(role);
List<ClientScopeRoleMappingEntity> results = query.getResultList();
if (results.size() == 0) return;
for (TemplateScopeMappingEntity entity : results) {
for (ClientScopeRoleMappingEntity entity : results) {
em.remove(entity);
}
}
protected TypedQuery<TemplateScopeMappingEntity> getRealmScopeMappingQuery(RoleModel role) {
TypedQuery<TemplateScopeMappingEntity> query = em.createNamedQuery("templateHasScope", TemplateScopeMappingEntity.class);
query.setParameter("template", getEntity());
protected TypedQuery<ClientScopeRoleMappingEntity> getRealmScopeMappingQuery(RoleModel role) {
TypedQuery<ClientScopeRoleMappingEntity> query = em.createNamedQuery("clientScopeHasRole", ClientScopeRoleMappingEntity.class);
query.setParameter("clientScope", getEntity());
RoleEntity roleEntity = RoleAdapter.toRoleEntity(role, em);
query.setParameter("role", roleEntity);
return query;
@ -288,7 +271,6 @@ public class ClientTemplateAdapter implements ClientTemplateModel , JpaModel<Cli
@Override
public boolean hasScope(RoleModel role) {
if (isFullScopeAllowed()) return true;
Set<RoleModel> roles = getScopeMappings();
if (roles.contains(role)) return true;
@ -298,26 +280,6 @@ public class ClientTemplateAdapter implements ClientTemplateModel , JpaModel<Cli
return false;
}
@Override
public boolean isPublicClient() {
return entity.isPublicClient();
}
@Override
public void setPublicClient(boolean flag) {
entity.setPublicClient(flag);
}
@Override
public boolean isFrontchannelLogout() {
return entity.isFrontchannelLogout();
}
@Override
public void setFrontchannelLogout(boolean flag) {
entity.setFrontchannelLogout(flag);
}
@Override
public void setAttribute(String name, String value) {
entity.getAttributes().put(name, value);
@ -334,6 +296,13 @@ public class ClientTemplateAdapter implements ClientTemplateModel , JpaModel<Cli
return entity.getAttributes().get(name);
}
public static ClientScopeEntity toClientScopeEntity(ClientScopeModel model, EntityManager em) {
if (model instanceof ClientScopeAdapter) {
return ((ClientScopeAdapter)model).getEntity();
}
return em.getReference(ClientScopeEntity.class, model.getId());
}
@Override
public Map<String, String> getAttributes() {
Map<String, String> copy = new HashMap<>();
@ -341,74 +310,13 @@ public class ClientTemplateAdapter implements ClientTemplateModel , JpaModel<Cli
return copy;
}
@Override
public boolean isBearerOnly() {
return entity.isBearerOnly();
}
@Override
public void setBearerOnly(boolean only) {
entity.setBearerOnly(only);
}
@Override
public boolean isConsentRequired() {
return entity.isConsentRequired();
}
@Override
public void setConsentRequired(boolean consentRequired) {
entity.setConsentRequired(consentRequired);
}
@Override
public boolean isStandardFlowEnabled() {
return entity.isStandardFlowEnabled();
}
@Override
public void setStandardFlowEnabled(boolean standardFlowEnabled) {
entity.setStandardFlowEnabled(standardFlowEnabled);
}
@Override
public boolean isImplicitFlowEnabled() {
return entity.isImplicitFlowEnabled();
}
@Override
public void setImplicitFlowEnabled(boolean implicitFlowEnabled) {
entity.setImplicitFlowEnabled(implicitFlowEnabled);
}
@Override
public boolean isDirectAccessGrantsEnabled() {
return entity.isDirectAccessGrantsEnabled();
}
@Override
public void setDirectAccessGrantsEnabled(boolean directAccessGrantsEnabled) {
entity.setDirectAccessGrantsEnabled(directAccessGrantsEnabled);
}
@Override
public boolean isServiceAccountsEnabled() {
return entity.isServiceAccountsEnabled();
}
@Override
public void setServiceAccountsEnabled(boolean serviceAccountsEnabled) {
entity.setServiceAccountsEnabled(serviceAccountsEnabled);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || !(o instanceof ClientTemplateModel)) return false;
if (o == null || !(o instanceof ClientScopeModel)) return false;
ClientTemplateModel that = (ClientTemplateModel) o;
ClientScopeModel that = (ClientScopeModel) o;
return that.getId().equals(getId());
}

View file

@ -23,7 +23,7 @@ import org.keycloak.connections.jpa.util.JpaUtils;
import org.keycloak.migration.MigrationModel;
import org.keycloak.models.ClientInitialAccessModel;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientTemplateModel;
import org.keycloak.models.ClientScopeModel;
import org.keycloak.models.GroupModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ModelDuplicateException;
@ -33,7 +33,7 @@ import org.keycloak.models.RoleContainerModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.jpa.entities.ClientEntity;
import org.keycloak.models.jpa.entities.ClientInitialAccessEntity;
import org.keycloak.models.jpa.entities.ClientTemplateEntity;
import org.keycloak.models.jpa.entities.ClientScopeEntity;
import org.keycloak.models.jpa.entities.GroupEntity;
import org.keycloak.models.jpa.entities.RealmEntity;
import org.keycloak.models.jpa.entities.RoleEntity;
@ -142,8 +142,11 @@ public class JpaRealmProvider implements RealmProvider {
removeClient(client, adapter);
}
for (ClientTemplateEntity a : new LinkedList<>(realm.getClientTemplates())) {
adapter.removeClientTemplate(a.getId());
num = em.createNamedQuery("deleteDefaultClientScopeRealmMappingByRealm")
.setParameter("realm", realm).executeUpdate();
for (ClientScopeEntity a : new LinkedList<>(realm.getClientScopes())) {
adapter.removeClientScope(a.getId());
}
for (RoleModel role : adapter.getRoles()) {
@ -285,7 +288,7 @@ public class JpaRealmProvider implements RealmProvider {
String compositeRoleTable = JpaUtils.getTableNameForNativeQuery("COMPOSITE_ROLE", em);
em.createNativeQuery("delete from " + compositeRoleTable + " where CHILD_ROLE = :role").setParameter("role", roleEntity).executeUpdate();
realm.getClients().forEach(c -> c.deleteScopeMapping(role));
em.createNamedQuery("deleteTemplateScopeMappingByRole").setParameter("role", roleEntity).executeUpdate();
em.createNamedQuery("deleteClientScopeRoleMappingByRole").setParameter("role", roleEntity).executeUpdate();
int val = em.createNamedQuery("deleteGroupRoleMappingsByRole").setParameter("roleId", roleEntity.getId()).executeUpdate();
em.flush();
@ -567,6 +570,9 @@ public class JpaRealmProvider implements RealmProvider {
}
});
int countRemoved = em.createNamedQuery("deleteClientScopeClientMappingByClient")
.setParameter("client", clientEntity)
.executeUpdate();
em.remove(clientEntity); // i have no idea why, but this needs to come before deleteScopeMapping
try {
@ -580,12 +586,12 @@ public class JpaRealmProvider implements RealmProvider {
}
@Override
public ClientTemplateModel getClientTemplateById(String id, RealmModel realm) {
ClientTemplateEntity app = em.find(ClientTemplateEntity.class, id);
public ClientScopeModel getClientScopeById(String id, RealmModel realm) {
ClientScopeEntity app = em.find(ClientScopeEntity.class, id);
// Check if application belongs to this realm
if (app == null || !realm.getId().equals(app.getRealm().getId())) return null;
ClientTemplateAdapter adapter = new ClientTemplateAdapter(realm, em, session, app);
ClientScopeAdapter adapter = new ClientScopeAdapter(realm, em, session, app);
return adapter;
}

View file

@ -23,7 +23,7 @@ import org.keycloak.component.ComponentModel;
import org.keycloak.credential.CredentialModel;
import org.keycloak.credential.UserCredentialStore;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientTemplateModel;
import org.keycloak.models.ClientScopeModel;
import org.keycloak.models.FederatedIdentityModel;
import org.keycloak.models.GroupModel;
import org.keycloak.models.KeycloakSession;
@ -39,9 +39,8 @@ import org.keycloak.models.UserProvider;
import org.keycloak.models.jpa.entities.CredentialAttributeEntity;
import org.keycloak.models.jpa.entities.CredentialEntity;
import org.keycloak.models.jpa.entities.FederatedIdentityEntity;
import org.keycloak.models.jpa.entities.UserConsentClientScopeEntity;
import org.keycloak.models.jpa.entities.UserConsentEntity;
import org.keycloak.models.jpa.entities.UserConsentProtocolMapperEntity;
import org.keycloak.models.jpa.entities.UserConsentRoleEntity;
import org.keycloak.models.jpa.entities.UserEntity;
import org.keycloak.models.utils.DefaultRoles;
import org.keycloak.models.utils.KeycloakModelUtils;
@ -132,8 +131,7 @@ public class JpaUserProvider implements UserProvider, UserCredentialStore {
em.createNamedQuery("deleteUserRoleMappingsByUser").setParameter("user", user).executeUpdate();
em.createNamedQuery("deleteUserGroupMembershipsByUser").setParameter("user", user).executeUpdate();
em.createNamedQuery("deleteFederatedIdentityByUser").setParameter("user", user).executeUpdate();
em.createNamedQuery("deleteUserConsentRolesByUser").setParameter("user", user).executeUpdate();
em.createNamedQuery("deleteUserConsentProtMappersByUser").setParameter("user", user).executeUpdate();
em.createNamedQuery("deleteUserConsentClientScopesByUser").setParameter("user", user).executeUpdate();
em.createNamedQuery("deleteUserConsentsByUser").setParameter("user", user).executeUpdate();
em.flush();
// not sure why i have to do a clear() here. I was getting some messed up errors that Hibernate couldn't
@ -297,36 +295,12 @@ public class JpaUserProvider implements UserProvider, UserCredentialStore {
model.setCreatedDate(entity.getCreatedDate());
model.setLastUpdatedDate(entity.getLastUpdatedDate());
Collection<UserConsentRoleEntity> grantedRoleEntities = entity.getGrantedRoles();
if (grantedRoleEntities != null) {
for (UserConsentRoleEntity grantedRole : grantedRoleEntities) {
RoleModel grantedRoleModel = realm.getRoleById(grantedRole.getRoleId());
if (grantedRoleModel != null) {
model.addGrantedRole(grantedRoleModel);
}
}
}
Collection<UserConsentProtocolMapperEntity> grantedProtocolMapperEntities = entity.getGrantedProtocolMappers();
if (grantedProtocolMapperEntities != null) {
ClientTemplateModel clientTemplate = null;
if (client.useTemplateMappers()) {
clientTemplate = client.getClientTemplate();
}
for (UserConsentProtocolMapperEntity grantedProtMapper : grantedProtocolMapperEntities) {
ProtocolMapperModel protocolMapper = client.getProtocolMapperById(grantedProtMapper.getProtocolMapperId());
// Fallback to client template
if (protocolMapper == null) {
if (clientTemplate != null) {
protocolMapper = clientTemplate.getProtocolMapperById(grantedProtMapper.getProtocolMapperId());
}
}
if (protocolMapper != null) {
model.addGrantedProtocolMapper(protocolMapper);
Collection<UserConsentClientScopeEntity> grantedClientScopeEntities = entity.getGrantedClientScopes();
if (grantedClientScopeEntities != null) {
for (UserConsentClientScopeEntity grantedClientScope : grantedClientScopeEntities) {
ClientScopeModel grantedClientScopeModel = KeycloakModelUtils.findClientScopeById(realm, grantedClientScope.getScopeId());
if (grantedClientScopeModel != null) {
model.addGrantedClientScope(grantedClientScopeModel);
}
}
}
@ -336,48 +310,26 @@ public class JpaUserProvider implements UserProvider, UserCredentialStore {
// Update roles and protocolMappers to given consentEntity from the consentModel
private void updateGrantedConsentEntity(UserConsentEntity consentEntity, UserConsentModel consentModel) {
Collection<UserConsentProtocolMapperEntity> grantedProtocolMapperEntities = consentEntity.getGrantedProtocolMappers();
Collection<UserConsentProtocolMapperEntity> mappersToRemove = new HashSet<UserConsentProtocolMapperEntity>(grantedProtocolMapperEntities);
Collection<UserConsentClientScopeEntity> grantedClientScopeEntities = consentEntity.getGrantedClientScopes();
Collection<UserConsentClientScopeEntity> scopesToRemove = new HashSet<>(grantedClientScopeEntities);
for (ProtocolMapperModel protocolMapper : consentModel.getGrantedProtocolMappers()) {
UserConsentProtocolMapperEntity grantedProtocolMapperEntity = new UserConsentProtocolMapperEntity();
grantedProtocolMapperEntity.setUserConsent(consentEntity);
grantedProtocolMapperEntity.setProtocolMapperId(protocolMapper.getId());
for (ClientScopeModel clientScope : consentModel.getGrantedClientScopes()) {
UserConsentClientScopeEntity grantedClientScopeEntity = new UserConsentClientScopeEntity();
grantedClientScopeEntity.setUserConsent(consentEntity);
grantedClientScopeEntity.setScopeId(clientScope.getId());
// Check if it's already there
if (!grantedProtocolMapperEntities.contains(grantedProtocolMapperEntity)) {
em.persist(grantedProtocolMapperEntity);
if (!grantedClientScopeEntities.contains(grantedClientScopeEntity)) {
em.persist(grantedClientScopeEntity);
em.flush();
grantedProtocolMapperEntities.add(grantedProtocolMapperEntity);
grantedClientScopeEntities.add(grantedClientScopeEntity);
} else {
mappersToRemove.remove(grantedProtocolMapperEntity);
scopesToRemove.remove(grantedClientScopeEntity);
}
}
// Those mappers were no longer on consentModel and will be removed
for (UserConsentProtocolMapperEntity toRemove : mappersToRemove) {
grantedProtocolMapperEntities.remove(toRemove);
em.remove(toRemove);
}
Collection<UserConsentRoleEntity> grantedRoleEntities = consentEntity.getGrantedRoles();
Set<UserConsentRoleEntity> rolesToRemove = new HashSet<UserConsentRoleEntity>(grantedRoleEntities);
for (RoleModel role : consentModel.getGrantedRoles()) {
UserConsentRoleEntity consentRoleEntity = new UserConsentRoleEntity();
consentRoleEntity.setUserConsent(consentEntity);
consentRoleEntity.setRoleId(role.getId());
// Check if it's already there
if (!grantedRoleEntities.contains(consentRoleEntity)) {
em.persist(consentRoleEntity);
em.flush();
grantedRoleEntities.add(consentRoleEntity);
} else {
rolesToRemove.remove(consentRoleEntity);
}
}
// Those roles were no longer on consentModel and will be removed
for (UserConsentRoleEntity toRemove : rolesToRemove) {
grantedRoleEntities.remove(toRemove);
// Those client scopes were no longer on consentModel and will be removed
for (UserConsentClientScopeEntity toRemove : scopesToRemove) {
grantedClientScopeEntities.remove(toRemove);
em.remove(toRemove);
}
@ -409,9 +361,7 @@ public class JpaUserProvider implements UserProvider, UserCredentialStore {
@Override
public void preRemove(RealmModel realm) {
int num = em.createNamedQuery("deleteUserConsentRolesByRealm")
.setParameter("realmId", realm.getId()).executeUpdate();
num = em.createNamedQuery("deleteUserConsentProtMappersByRealm")
int num = em.createNamedQuery("deleteUserConsentClientScopesByRealm")
.setParameter("realmId", realm.getId()).executeUpdate();
num = em.createNamedQuery("deleteUserConsentsByRealm")
.setParameter("realmId", realm.getId()).executeUpdate();
@ -463,11 +413,7 @@ public class JpaUserProvider implements UserProvider, UserCredentialStore {
.setParameter("realmId", realm.getId())
.setParameter("link", storageProviderId)
.executeUpdate();
num = em.createNamedQuery("deleteUserConsentProtMappersByRealmAndLink")
.setParameter("realmId", realm.getId())
.setParameter("link", storageProviderId)
.executeUpdate();
num = em.createNamedQuery("deleteUserConsentRolesByRealmAndLink")
num = em.createNamedQuery("deleteUserConsentClientScopesByRealmAndLink")
.setParameter("realmId", realm.getId())
.setParameter("link", storageProviderId)
.executeUpdate();
@ -491,7 +437,6 @@ public class JpaUserProvider implements UserProvider, UserCredentialStore {
@Override
public void preRemove(RealmModel realm, RoleModel role) {
em.createNamedQuery("deleteUserConsentRolesByRole").setParameter("roleId", role.getId()).executeUpdate();
em.createNamedQuery("deleteUserRoleMappingsByRole").setParameter("roleId", role.getId()).executeUpdate();
}
@ -499,21 +444,14 @@ public class JpaUserProvider implements UserProvider, UserCredentialStore {
public void preRemove(RealmModel realm, ClientModel client) {
StorageId clientStorageId = new StorageId(client.getId());
if (clientStorageId.isLocal()) {
em.createNamedQuery("deleteUserConsentProtMappersByClient")
int num = em.createNamedQuery("deleteUserConsentClientScopesByClient")
.setParameter("clientId", client.getId())
.executeUpdate();
em.createNamedQuery("deleteUserConsentRolesByClient")
.setParameter("clientId", client.getId())
.executeUpdate();
em.createNamedQuery("deleteUserConsentsByClient")
num = em.createNamedQuery("deleteUserConsentsByClient")
.setParameter("clientId", client.getId())
.executeUpdate();
} else {
em.createNamedQuery("deleteUserConsentProtMappersByExternalClient")
.setParameter("clientStorageProvider", clientStorageId.getProviderId())
.setParameter("externalClientId",clientStorageId.getExternalId())
.executeUpdate();
em.createNamedQuery("deleteUserConsentRolesByExternalClient")
em.createNamedQuery("deleteUserConsentClientScopesByExternalClient")
.setParameter("clientStorageProvider", clientStorageId.getProviderId())
.setParameter("externalClientId", clientStorageId.getExternalId())
.executeUpdate();
@ -527,8 +465,13 @@ public class JpaUserProvider implements UserProvider, UserCredentialStore {
@Override
public void preRemove(ProtocolMapperModel protocolMapper) {
em.createNamedQuery("deleteUserConsentProtMappersByProtocolMapper")
.setParameter("protocolMapperId", protocolMapper.getId())
// No-op
}
@Override
public void preRemove(ClientScopeModel clientScope) {
em.createNamedQuery("deleteUserConsentClientScopesByClientScope")
.setParameter("scopeId", clientScope.getId())
.executeUpdate();
}
@ -863,10 +806,7 @@ public class JpaUserProvider implements UserProvider, UserCredentialStore {
}
protected void removeConsentByClientStorageProvider(RealmModel realm, String providerId) {
em.createNamedQuery("deleteUserConsentProtMappersByClientStorageProvider")
.setParameter("clientStorageProvider", providerId)
.executeUpdate();
em.createNamedQuery("deleteUserConsentRolesByClientStorageProvider")
em.createNamedQuery("deleteUserConsentClientScopesByClientStorageProvider")
.setParameter("clientStorageProvider", providerId)
.executeUpdate();
em.createNamedQuery("deleteUserConsentsByClientStorageProvider")

View file

@ -28,6 +28,8 @@ import org.keycloak.models.utils.ComponentUtil;
import org.keycloak.models.utils.KeycloakModelUtils;
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;
@ -1769,60 +1771,64 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
}
@Override
public List<ClientTemplateModel> getClientTemplates() {
Collection<ClientTemplateEntity> entities = realm.getClientTemplates();
public List<ClientScopeModel> getClientScopes() {
Collection<ClientScopeEntity> entities = realm.getClientScopes();
if (entities == null || entities.isEmpty()) return Collections.EMPTY_LIST;
List<ClientTemplateModel> list = new LinkedList<>();
for (ClientTemplateEntity entity : entities) {
list.add(session.realms().getClientTemplateById(entity.getId(), this));
List<ClientScopeModel> list = new LinkedList<>();
for (ClientScopeEntity entity : entities) {
list.add(session.realms().getClientScopeById(entity.getId(), this));
}
return Collections.unmodifiableList(list);
}
@Override
public ClientTemplateModel addClientTemplate(String name) {
return this.addClientTemplate(KeycloakModelUtils.generateId(), name);
public ClientScopeModel addClientScope(String name) {
return this.addClientScope(KeycloakModelUtils.generateId(), name);
}
@Override
public ClientTemplateModel addClientTemplate(String id, String name) {
ClientTemplateEntity entity = new ClientTemplateEntity();
public ClientScopeModel addClientScope(String id, String name) {
ClientScopeEntity entity = new ClientScopeEntity();
entity.setId(id);
name = KeycloakModelUtils.convertClientScopeName(name);
entity.setName(name);
entity.setRealm(realm);
realm.getClientTemplates().add(entity);
realm.getClientScopes().add(entity);
em.persist(entity);
em.flush();
final ClientTemplateModel resource = new ClientTemplateAdapter(this, em, session, entity);
final ClientScopeModel resource = new ClientScopeAdapter(this, em, session, entity);
em.flush();
return resource;
}
@Override
public boolean removeClientTemplate(String id) {
public boolean removeClientScope(String id) {
if (id == null) return false;
ClientTemplateModel client = getClientTemplateById(id);
if (client == null) return false;
if (KeycloakModelUtils.isClientTemplateUsed(this, client)) {
throw new ModelException("Cannot remove client template, it is currently in use");
ClientScopeModel clientScope = getClientScopeById(id);
if (clientScope == null) return false;
if (KeycloakModelUtils.isClientScopeUsed(this, clientScope)) {
throw new ModelException("Cannot remove client scope, it is currently in use");
}
ClientTemplateEntity clientEntity = null;
Iterator<ClientTemplateEntity> it = realm.getClientTemplates().iterator();
ClientScopeEntity clientScopeEntity = null;
Iterator<ClientScopeEntity> it = realm.getClientScopes().iterator();
while (it.hasNext()) {
ClientTemplateEntity ae = it.next();
ClientScopeEntity ae = it.next();
if (ae.getId().equals(id)) {
clientEntity = ae;
clientScopeEntity = ae;
it.remove();
break;
}
}
if (client == null) {
if (clientScope == null) {
return false;
}
em.createNamedQuery("deleteTemplateScopeMappingByClient").setParameter("template", clientEntity).executeUpdate();
session.users().preRemove(clientScope);
em.createNamedQuery("deleteClientScopeRoleMappingByClientScope").setParameter("clientScope", clientScopeEntity).executeUpdate();
em.flush();
em.remove(clientEntity);
em.remove(clientScopeEntity);
em.flush();
@ -1830,8 +1836,44 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
}
@Override
public ClientTemplateModel getClientTemplateById(String id) {
return session.realms().getClientTemplateById(id, this);
public ClientScopeModel getClientScopeById(String id) {
return session.realms().getClientScopeById(id, this);
}
@Override
public void addDefaultClientScope(ClientScopeModel clientScope, boolean defaultScope) {
DefaultClientScopeRealmMappingEntity entity = new DefaultClientScopeRealmMappingEntity();
entity.setClientScope(ClientScopeAdapter.toClientScopeEntity(clientScope, em));
entity.setRealm(getEntity());
entity.setDefaultScope(defaultScope);
em.persist(entity);
em.flush();
em.detach(entity);
}
@Override
public void removeDefaultClientScope(ClientScopeModel clientScope) {
int numRemoved = em.createNamedQuery("deleteDefaultClientScopeRealmMapping")
.setParameter("clientScope", ClientScopeAdapter.toClientScopeEntity(clientScope, em))
.setParameter("realm", getEntity())
.executeUpdate();
em.flush();
}
@Override
public List<ClientScopeModel> getDefaultClientScopes(boolean defaultScope) {
TypedQuery<String> query = em.createNamedQuery("defaultClientScopeRealmMappingIdsByRealm", String.class);
query.setParameter("realm", getEntity());
query.setParameter("defaultScope", defaultScope);
List<String> ids = query.getResultList();
List<ClientScopeModel> clientScopes = new LinkedList<>();
for (String clientScopeId : ids) {
ClientScopeModel clientScope = getClientScopeById(clientScopeId);
if (clientScope == null) continue;
clientScopes.add(clientScope);
}
return clientScopes;
}
@Override

View file

@ -68,16 +68,6 @@ public class RoleAdapter implements RoleModel, JpaModel<RoleEntity> {
role.setDescription(description);
}
@Override
public boolean isScopeParamRequired() {
return role.isScopeParamRequired();
}
@Override
public void setScopeParamRequired(boolean scopeParamRequired) {
role.setScopeParamRequired(scopeParamRequired);
}
@Override
public String getId() {
return role.getId();

View file

@ -90,19 +90,6 @@ public class ClientEntity {
@Column(name="FULL_SCOPE_ALLOWED")
private boolean fullScopeAllowed;
@ManyToOne(fetch = FetchType.LAZY)
@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;
@ -435,38 +422,6 @@ public class ClientEntity {
this.registeredNodes = registeredNodes;
}
public ClientTemplateEntity getClientTemplate() {
return clientTemplate;
}
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;
}
public Set<RoleEntity> getScopeMapping() {
return scopeMapping;
}

View file

@ -0,0 +1,148 @@
/*
* Copyright 2017 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.models.jpa.entities;
import java.io.Serializable;
import javax.persistence.Column;
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;
/**
* Binding between client and clientScope
*
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
@NamedQueries({
@NamedQuery(name="clientScopeClientMappingIdsByClient", query="select m.clientScope.id from ClientScopeClientMappingEntity m where m.client = :client and m.defaultScope = :defaultScope"),
@NamedQuery(name="deleteClientScopeClientMapping", query="delete from ClientScopeClientMappingEntity where client = :client and clientScope = :clientScope"),
@NamedQuery(name="deleteClientScopeClientMappingByClient", query="delete from ClientScopeClientMappingEntity where client = :client")
})
@Entity
@Table(name="CLIENT_SCOPE_CLIENT")
@IdClass(ClientScopeClientMappingEntity.Key.class)
public class ClientScopeClientMappingEntity {
@Id
@ManyToOne(fetch= FetchType.LAZY)
@JoinColumn(name = "SCOPE_ID")
protected ClientScopeEntity clientScope;
@Id
@ManyToOne(fetch= FetchType.LAZY)
@JoinColumn(name="CLIENT_ID")
protected ClientEntity client;
@Column(name="DEFAULT_SCOPE")
protected boolean defaultScope;
public ClientScopeEntity getClientScope() {
return clientScope;
}
public void setClientScope(ClientScopeEntity clientScope) {
this.clientScope = clientScope;
}
public ClientEntity getClient() {
return client;
}
public void setClient(ClientEntity client) {
this.client = client;
}
public boolean isDefaultScope() {
return defaultScope;
}
public void setDefaultScope(boolean defaultScope) {
this.defaultScope = defaultScope;
}
public static class Key implements Serializable {
protected ClientScopeEntity clientScope;
protected ClientEntity client;
public Key() {
}
public Key(ClientScopeEntity clientScope, ClientEntity client) {
this.clientScope = clientScope;
this.client = client;
}
public ClientScopeEntity getClientScope() {
return clientScope;
}
public ClientEntity getClient() {
return client;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ClientScopeClientMappingEntity.Key key = (ClientScopeClientMappingEntity.Key) o;
if (clientScope != null ? !clientScope.getId().equals(key.clientScope != null ? key.clientScope.getId() : null) : key.clientScope != null) return false;
if (client != null ? !client.getId().equals(key.client != null ? key.client.getId() : null) : key.client != null) return false;
return true;
}
@Override
public int hashCode() {
int result = clientScope != null ? clientScope.getId().hashCode() : 0;
result = 31 * result + (client != null ? client.getId().hashCode() : 0);
return result;
}
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!(o instanceof ClientScopeClientMappingEntity)) return false;
ClientScopeClientMappingEntity key = (ClientScopeClientMappingEntity) o;
if (clientScope != null ? !clientScope.getId().equals(key.clientScope != null ? key.clientScope.getId() : null) : key.clientScope != null) return false;
if (client != null ? !client.getId().equals(key.client != null ? key.client.getId() : null) : key.client != null) return false;
return true;
}
@Override
public int hashCode() {
int result = clientScope != null ? clientScope.getId().hashCode() : 0;
result = 31 * result + (client != null ? client.getId().hashCode() : 0);
return result;
}
}

View file

@ -44,8 +44,8 @@ import java.util.Map;
* @version $Revision: 1 $
*/
@Entity
@Table(name="CLIENT_TEMPLATE", uniqueConstraints = {@UniqueConstraint(columnNames = {"REALM_ID", "NAME"})})
public class ClientTemplateEntity {
@Table(name="CLIENT_SCOPE", uniqueConstraints = {@UniqueConstraint(columnNames = {"REALM_ID", "NAME"})})
public class ClientScopeEntity {
@Id
@Column(name="ID", length = 36)
@ -56,7 +56,7 @@ public class ClientTemplateEntity {
@Nationalized
@Column(name = "DESCRIPTION")
private String description;
@OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "clientTemplate")
@OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "clientScope")
Collection<ProtocolMapperEntity> protocolMappers = new ArrayList<ProtocolMapperEntity>();
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "REALM_ID")
@ -65,36 +65,11 @@ public class ClientTemplateEntity {
@Column(name="PROTOCOL")
private String protocol;
@Column(name="FULL_SCOPE_ALLOWED")
private boolean fullScopeAllowed;
@Column(name="CONSENT_REQUIRED")
private boolean consentRequired;
@Column(name="STANDARD_FLOW_ENABLED")
private boolean standardFlowEnabled;
@Column(name="IMPLICIT_FLOW_ENABLED")
private boolean implicitFlowEnabled;
@Column(name="DIRECT_ACCESS_GRANTS_ENABLED")
private boolean directAccessGrantsEnabled;
@Column(name="SERVICE_ACCOUNTS_ENABLED")
private boolean serviceAccountsEnabled;
@Column(name="FRONTCHANNEL_LOGOUT")
private boolean frontchannelLogout;
@Column(name="PUBLIC_CLIENT")
private boolean publicClient;
@Column(name="BEARER_ONLY")
private boolean bearerOnly;
@ElementCollection
@MapKeyColumn(name="NAME")
@Column(name="VALUE", length = 2048)
@CollectionTable(name="CLIENT_TEMPLATE_ATTRIBUTES", joinColumns={ @JoinColumn(name="TEMPLATE_ID") })
@CollectionTable(name="CLIENT_SCOPE_ATTRIBUTES", joinColumns={ @JoinColumn(name="SCOPE_ID") })
protected Map<String, String> attributes = new HashMap<String, String>();
public RealmEntity getRealm() {
@ -145,14 +120,6 @@ public class ClientTemplateEntity {
this.protocol = protocol;
}
public boolean isFullScopeAllowed() {
return fullScopeAllowed;
}
public void setFullScopeAllowed(boolean fullScopeAllowed) {
this.fullScopeAllowed = fullScopeAllowed;
}
public Map<String, String> getAttributes() {
return attributes;
}
@ -161,77 +128,13 @@ public class ClientTemplateEntity {
this.attributes = attributes;
}
public boolean isConsentRequired() {
return consentRequired;
}
public void setConsentRequired(boolean consentRequired) {
this.consentRequired = consentRequired;
}
public boolean isStandardFlowEnabled() {
return standardFlowEnabled;
}
public void setStandardFlowEnabled(boolean standardFlowEnabled) {
this.standardFlowEnabled = standardFlowEnabled;
}
public boolean isImplicitFlowEnabled() {
return implicitFlowEnabled;
}
public void setImplicitFlowEnabled(boolean implicitFlowEnabled) {
this.implicitFlowEnabled = implicitFlowEnabled;
}
public boolean isDirectAccessGrantsEnabled() {
return directAccessGrantsEnabled;
}
public void setDirectAccessGrantsEnabled(boolean directAccessGrantsEnabled) {
this.directAccessGrantsEnabled = directAccessGrantsEnabled;
}
public boolean isServiceAccountsEnabled() {
return serviceAccountsEnabled;
}
public void setServiceAccountsEnabled(boolean serviceAccountsEnabled) {
this.serviceAccountsEnabled = serviceAccountsEnabled;
}
public boolean isFrontchannelLogout() {
return frontchannelLogout;
}
public void setFrontchannelLogout(boolean frontchannelLogout) {
this.frontchannelLogout = frontchannelLogout;
}
public boolean isPublicClient() {
return publicClient;
}
public void setPublicClient(boolean publicClient) {
this.publicClient = publicClient;
}
public boolean isBearerOnly() {
return bearerOnly;
}
public void setBearerOnly(boolean bearerOnly) {
this.bearerOnly = bearerOnly;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null) return false;
if (!(o instanceof ClientTemplateEntity)) return false;
if (!(o instanceof ClientScopeEntity)) return false;
ClientTemplateEntity that = (ClientTemplateEntity) o;
ClientScopeEntity that = (ClientScopeEntity) o;
if (!id.equals(that.getId())) return false;

View file

@ -33,33 +33,32 @@ import java.io.Serializable;
* @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")
@NamedQuery(name="clientScopeHasRole", query="select m from ClientScopeRoleMappingEntity m where m.clientScope = :clientScope and m.role = :role"),
@NamedQuery(name="clientScopeRoleMappingIds", query="select m.role.id from ClientScopeRoleMappingEntity m where m.clientScope = :clientScope"),
@NamedQuery(name="deleteClientScopeRoleMappingByRole", query="delete from ClientScopeRoleMappingEntity where role = :role"),
@NamedQuery(name="deleteClientScopeRoleMappingByClientScope", query="delete from ClientScopeRoleMappingEntity where clientScope = :clientScope")
})
@Table(name="TEMPLATE_SCOPE_MAPPING")
@Table(name="CLIENT_SCOPE_ROLE_MAPPING")
@Entity
@IdClass(TemplateScopeMappingEntity.Key.class)
public class TemplateScopeMappingEntity {
@IdClass(ClientScopeRoleMappingEntity.Key.class)
public class ClientScopeRoleMappingEntity {
@Id
@ManyToOne(fetch= FetchType.LAZY)
@JoinColumn(name = "TEMPLATE_ID")
protected ClientTemplateEntity template;
@JoinColumn(name = "SCOPE_ID")
protected ClientScopeEntity clientScope;
@Id
@ManyToOne(fetch= FetchType.LAZY)
@JoinColumn(name="ROLE_ID")
protected RoleEntity role;
public ClientTemplateEntity getTemplate() {
return template;
public ClientScopeEntity getClientScope() {
return clientScope;
}
public void setTemplate(ClientTemplateEntity template) {
this.template = template;
public void setClientScope(ClientScopeEntity clientScope) {
this.clientScope = clientScope;
}
public RoleEntity getRole() {
@ -72,20 +71,20 @@ public class TemplateScopeMappingEntity {
public static class Key implements Serializable {
protected ClientTemplateEntity template;
protected ClientScopeEntity clientScope;
protected RoleEntity role;
public Key() {
}
public Key(ClientTemplateEntity template, RoleEntity role) {
this.template = template;
public Key(ClientScopeEntity clientScope, RoleEntity role) {
this.clientScope = clientScope;
this.role = role;
}
public ClientTemplateEntity getTemplate() {
return template;
public ClientScopeEntity getClientScope() {
return clientScope;
}
public RoleEntity getRole() {
@ -99,7 +98,7 @@ public class TemplateScopeMappingEntity {
Key key = (Key) o;
if (template != null ? !template.getId().equals(key.template != null ? key.template.getId() : null) : key.template != null) return false;
if (clientScope != null ? !clientScope.getId().equals(key.clientScope != null ? key.clientScope.getId() : null) : key.clientScope != null) return false;
if (role != null ? !role.getId().equals(key.role != null ? key.role.getId() : null) : key.role != null) return false;
return true;
@ -107,7 +106,7 @@ public class TemplateScopeMappingEntity {
@Override
public int hashCode() {
int result = template != null ? template.getId().hashCode() : 0;
int result = clientScope != null ? clientScope.getId().hashCode() : 0;
result = 31 * result + (role != null ? role.getId().hashCode() : 0);
return result;
}
@ -117,11 +116,11 @@ public class TemplateScopeMappingEntity {
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!(o instanceof TemplateScopeMappingEntity)) return false;
if (!(o instanceof ClientScopeRoleMappingEntity)) return false;
TemplateScopeMappingEntity key = (TemplateScopeMappingEntity) o;
ClientScopeRoleMappingEntity key = (ClientScopeRoleMappingEntity) o;
if (template != null ? !template.getId().equals(key.template != null ? key.template.getId() : null) : key.template != null) return false;
if (clientScope != null ? !clientScope.getId().equals(key.clientScope != null ? key.clientScope.getId() : null) : key.clientScope != null) return false;
if (role != null ? !role.getId().equals(key.role != null ? key.role.getId() : null) : key.role != null) return false;
return true;
@ -129,7 +128,7 @@ public class TemplateScopeMappingEntity {
@Override
public int hashCode() {
int result = template != null ? template.getId().hashCode() : 0;
int result = clientScope != null ? clientScope.getId().hashCode() : 0;
result = 31 * result + (role != null ? role.getId().hashCode() : 0);
return result;
}

View file

@ -0,0 +1,148 @@
/*
* Copyright 2017 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.models.jpa.entities;
import java.io.Serializable;
import javax.persistence.Column;
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;
/**
* Binding between realm and default clientScope
*
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
@NamedQueries({
@NamedQuery(name="defaultClientScopeRealmMappingIdsByRealm", query="select m.clientScope.id from DefaultClientScopeRealmMappingEntity m where m.realm = :realm and m.defaultScope = :defaultScope"),
@NamedQuery(name="deleteDefaultClientScopeRealmMapping", query="delete from DefaultClientScopeRealmMappingEntity where realm = :realm and clientScope = :clientScope"),
@NamedQuery(name="deleteDefaultClientScopeRealmMappingByRealm", query="delete from DefaultClientScopeRealmMappingEntity where realm = :realm")
})
@Entity
@Table(name="DEFAULT_CLIENT_SCOPE")
@IdClass(DefaultClientScopeRealmMappingEntity.Key.class)
public class DefaultClientScopeRealmMappingEntity {
@Id
@ManyToOne(fetch= FetchType.LAZY)
@JoinColumn(name = "SCOPE_ID")
protected ClientScopeEntity clientScope;
@Id
@ManyToOne(fetch= FetchType.LAZY)
@JoinColumn(name="REALM_ID")
protected RealmEntity realm;
@Column(name="DEFAULT_SCOPE")
protected boolean defaultScope;
public ClientScopeEntity getClientScope() {
return clientScope;
}
public void setClientScope(ClientScopeEntity clientScope) {
this.clientScope = clientScope;
}
public RealmEntity getRealm() {
return realm;
}
public void setRealm(RealmEntity realm) {
this.realm = realm;
}
public boolean isDefaultScope() {
return defaultScope;
}
public void setDefaultScope(boolean defaultScope) {
this.defaultScope = defaultScope;
}
public static class Key implements Serializable {
protected ClientScopeEntity clientScope;
protected RealmEntity realm;
public Key() {
}
public Key(ClientScopeEntity clientScope, RealmEntity realm) {
this.clientScope = clientScope;
this.realm = realm;
}
public ClientScopeEntity getClientScope() {
return clientScope;
}
public RealmEntity getRealm() {
return realm;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
DefaultClientScopeRealmMappingEntity.Key key = (DefaultClientScopeRealmMappingEntity.Key) o;
if (clientScope != null ? !clientScope.getId().equals(key.clientScope != null ? key.clientScope.getId() : null) : key.clientScope != null) return false;
if (realm != null ? !realm.getId().equals(key.realm != null ? key.realm.getId() : null) : key.realm != null) return false;
return true;
}
@Override
public int hashCode() {
int result = clientScope != null ? clientScope.getId().hashCode() : 0;
result = 31 * result + (realm != null ? realm.getId().hashCode() : 0);
return result;
}
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!(o instanceof DefaultClientScopeRealmMappingEntity)) return false;
DefaultClientScopeRealmMappingEntity key = (DefaultClientScopeRealmMappingEntity) o;
if (clientScope != null ? !clientScope.getId().equals(key.clientScope != null ? key.clientScope.getId() : null) : key.clientScope != null) return false;
if (realm != null ? !realm.getId().equals(key.realm != null ? key.realm.getId() : null) : key.realm != null) return false;
return true;
}
@Override
public int hashCode() {
int result = clientScope != null ? clientScope.getId().hashCode() : 0;
result = 31 * result + (realm != null ? realm.getId().hashCode() : 0);
return result;
}
}

View file

@ -51,10 +51,6 @@ public class ProtocolMapperEntity {
protected String protocol;
@Column(name = "PROTOCOL_MAPPER_NAME")
protected String protocolMapper;
@Column(name="CONSENT_REQUIRED")
protected boolean consentRequired;
@Column(name="CONSENT_TEXT")
protected String consentText;
@ElementCollection
@MapKeyColumn(name="NAME")
@ -67,8 +63,8 @@ public class ProtocolMapperEntity {
private ClientEntity client;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "CLIENT_TEMPLATE_ID")
private ClientTemplateEntity clientTemplate;
@JoinColumn(name = "CLIENT_SCOPE_ID")
private ClientScopeEntity clientScope;
public String getId() {
return id;
@ -118,29 +114,14 @@ public class ProtocolMapperEntity {
this.client = client;
}
public ClientTemplateEntity getClientTemplate() {
return clientTemplate;
public ClientScopeEntity getClientScope() {
return clientScope;
}
public void setClientTemplate(ClientTemplateEntity clientTemplate) {
this.clientTemplate = clientTemplate;
public void setClientScope(ClientScopeEntity clientScope) {
this.clientScope = clientScope;
}
public boolean isConsentRequired() {
return consentRequired;
}
public void setConsentRequired(boolean consentRequired) {
this.consentRequired = consentRequired;
}
public String getConsentText() {
return consentText;
}
public void setConsentText(String consentText) {
this.consentText = consentText;
}
@Override
public boolean equals(Object o) {

View file

@ -145,7 +145,7 @@ public class RealmEntity {
Collection<UserFederationMapperEntity> userFederationMappers = new ArrayList<UserFederationMapperEntity>();
@OneToMany(fetch = FetchType.LAZY, cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "realm")
Collection<ClientTemplateEntity> clientTemplates = new ArrayList<>();
Collection<ClientScopeEntity> clientScopes = new ArrayList<>();
@ElementCollection
@MapKeyColumn(name="NAME")
@ -757,12 +757,12 @@ public class RealmEntity {
return this;
}
public Collection<ClientTemplateEntity> getClientTemplates() {
return clientTemplates;
public Collection<ClientScopeEntity> getClientScopes() {
return clientScopes;
}
public void setClientTemplates(Collection<ClientTemplateEntity> clientTemplates) {
this.clientTemplates = clientTemplates;
public void setClientScopes(Collection<ClientScopeEntity> clientScopes) {
this.clientScopes = clientScopes;
}
public void setAllowUserManagedAccess(boolean allowUserManagedAccess) {

View file

@ -69,8 +69,6 @@ public class RoleEntity {
@Nationalized
@Column(name = "DESCRIPTION")
private String description;
@Column(name = "SCOPE_PARAM_REQUIRED")
private boolean scopeParamRequired;
// hax! couldn't get constraint to work properly
@Column(name = "REALM_ID")
@ -129,14 +127,6 @@ public class RoleEntity {
this.description = description;
}
public boolean isScopeParamRequired() {
return scopeParamRequired;
}
public void setScopeParamRequired(boolean scopeParamRequired) {
this.scopeParamRequired = scopeParamRequired;
}
public Set<RoleEntity> getCompositeRoles() {
return compositeRoles;
}

View file

@ -0,0 +1,135 @@
/*
* Copyright 2017 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.models.jpa.entities;
import java.io.Serializable;
import javax.persistence.Column;
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;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
@NamedQueries({
@NamedQuery(name="deleteUserConsentClientScopesByRealm", query="delete from UserConsentClientScopeEntity grantedScope where grantedScope.userConsent IN (select consent from UserConsentEntity consent where consent.user IN (select user from UserEntity user where user.realmId = :realmId))"),
@NamedQuery(name="deleteUserConsentClientScopesByRealmAndLink", query="delete from UserConsentClientScopeEntity grantedScope where grantedScope.userConsent IN (select consent from UserConsentEntity consent where consent.user IN (select u from UserEntity u where u.realmId=:realmId and u.federationLink=:link))"),
@NamedQuery(name="deleteUserConsentClientScopesByUser", query="delete from UserConsentClientScopeEntity grantedScope where grantedScope.userConsent IN (select consent from UserConsentEntity consent where consent.user = :user)"),
@NamedQuery(name="deleteUserConsentClientScopesByClientScope", query="delete from UserConsentClientScopeEntity grantedScope where grantedScope.scopeId = :scopeId)"),
@NamedQuery(name="deleteUserConsentClientScopesByClient", query="delete from UserConsentClientScopeEntity grantedScope where grantedScope.userConsent IN (select consent from UserConsentEntity consent where consent.clientId = :clientId)"),
@NamedQuery(name="deleteUserConsentClientScopesByExternalClient", query="delete from UserConsentClientScopeEntity grantedScope where grantedScope.userConsent IN (select consent from UserConsentEntity consent where consent.clientStorageProvider = :clientStorageProvider and consent.externalClientId = :externalClientId)"),
@NamedQuery(name="deleteUserConsentClientScopesByClientStorageProvider", query="delete from UserConsentClientScopeEntity grantedScope where grantedScope.userConsent IN (select consent from UserConsentEntity consent where consent.clientStorageProvider = :clientStorageProvider)"),
})
@Entity
@Table(name="USER_CONSENT_CLIENT_SCOPE")
@IdClass(UserConsentClientScopeEntity.Key.class)
public class UserConsentClientScopeEntity {
@Id
@ManyToOne(fetch= FetchType.LAZY)
@JoinColumn(name = "USER_CONSENT_ID")
protected UserConsentEntity userConsent;
@Id
@Column(name="SCOPE_ID")
protected String scopeId;
public UserConsentEntity getUserConsent() {
return userConsent;
}
public void setUserConsent(UserConsentEntity userConsent) {
this.userConsent = userConsent;
}
public String getScopeId() {
return scopeId;
}
public void setScopeId(String scopeId) {
this.scopeId = scopeId;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null) return false;
if (!(o instanceof UserConsentClientScopeEntity)) return false;
UserConsentClientScopeEntity that = (UserConsentClientScopeEntity)o;
UserConsentClientScopeEntity.Key myKey = new UserConsentClientScopeEntity.Key(this.userConsent, this.scopeId);
UserConsentClientScopeEntity.Key hisKey = new UserConsentClientScopeEntity.Key(that.userConsent, that.scopeId);
return myKey.equals(hisKey);
}
@Override
public int hashCode() {
UserConsentClientScopeEntity.Key myKey = new UserConsentClientScopeEntity.Key(this.userConsent, this.scopeId);
return myKey.hashCode();
}
public static class Key implements Serializable {
protected UserConsentEntity userConsent;
protected String scopeId;
public Key() {
}
public Key(UserConsentEntity userConsent, String scopeId) {
this.userConsent = userConsent;
this.scopeId = scopeId;
}
public UserConsentEntity getUserConsent() {
return userConsent;
}
public String getScopeId() {
return scopeId;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
UserConsentClientScopeEntity.Key key = (UserConsentClientScopeEntity.Key) o;
if (userConsent != null ? !userConsent.getId().equals(key.userConsent != null ? key.userConsent.getId() : null) : key.userConsent != null) return false;
if (scopeId != null ? !scopeId.equals(key.scopeId) : key.scopeId != null) return false;
return true;
}
@Override
public int hashCode() {
int result = userConsent != null ? userConsent.getId().hashCode() : 0;
result = 31 * result + (scopeId != null ? scopeId.hashCode() : 0);
return result;
}
}
}

View file

@ -73,10 +73,7 @@ public class UserConsentEntity {
protected String externalClientId;
@OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "userConsent")
Collection<UserConsentRoleEntity> grantedRoles = new ArrayList<UserConsentRoleEntity>();
@OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "userConsent")
Collection<UserConsentProtocolMapperEntity> grantedProtocolMappers = new ArrayList<UserConsentProtocolMapperEntity>();
Collection<UserConsentClientScopeEntity> grantedClientScopes = new ArrayList<>();
@Column(name = "CREATED_DATE")
private Long createdDate;
@ -100,20 +97,12 @@ public class UserConsentEntity {
this.user = user;
}
public Collection<UserConsentRoleEntity> getGrantedRoles() {
return grantedRoles;
public Collection<UserConsentClientScopeEntity> getGrantedClientScopes() {
return grantedClientScopes;
}
public void setGrantedRoles(Collection<UserConsentRoleEntity> grantedRoles) {
this.grantedRoles = grantedRoles;
}
public Collection<UserConsentProtocolMapperEntity> getGrantedProtocolMappers() {
return grantedProtocolMappers;
}
public void setGrantedProtocolMappers(Collection<UserConsentProtocolMapperEntity> grantedProtocolMappers) {
this.grantedProtocolMappers = grantedProtocolMappers;
public void setGrantedClientScopes(Collection<UserConsentClientScopeEntity> grantedClientScopes) {
this.grantedClientScopes = grantedClientScopes;
}
public Long getCreatedDate() {

View file

@ -1,137 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.models.jpa.entities;
import javax.persistence.Column;
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:mposolda@redhat.com">Marek Posolda</a>
*/
@NamedQueries({
@NamedQuery(name="deleteUserConsentProtMappersByRealm", query=
"delete from UserConsentProtocolMapperEntity csm where csm.userConsent IN (select consent from UserConsentEntity consent where consent.user IN (select user from UserEntity user where user.realmId = :realmId))"),
@NamedQuery(name="deleteUserConsentProtMappersByUser", query="delete from UserConsentProtocolMapperEntity csm where csm.userConsent IN (select consent from UserConsentEntity consent where consent.user = :user)"),
@NamedQuery(name="deleteUserConsentProtMappersByRealmAndLink", query="delete from UserConsentProtocolMapperEntity csm where csm.userConsent IN (select consent from UserConsentEntity consent where consent.user IN (select u from UserEntity u where u.realmId=:realmId and u.federationLink=:link))"),
@NamedQuery(name="deleteUserConsentProtMappersByProtocolMapper", query="delete from UserConsentProtocolMapperEntity csm where csm.protocolMapperId = :protocolMapperId)"),
@NamedQuery(name="deleteUserConsentProtMappersByClient", query="delete from UserConsentProtocolMapperEntity csm where csm.userConsent IN (select consent from UserConsentEntity consent where consent.clientId = :clientId)"),
@NamedQuery(name="deleteUserConsentProtMappersByExternalClient", query="delete from UserConsentProtocolMapperEntity csm where csm.userConsent IN (select consent from UserConsentEntity consent where consent.clientStorageProvider = :clientStorageProvider and consent.externalClientId = :externalClientId)"),
@NamedQuery(name="deleteUserConsentProtMappersByClientStorageProvider", query="delete from UserConsentProtocolMapperEntity csm where csm.userConsent IN (select consent from UserConsentEntity consent where consent.clientStorageProvider = :clientStorageProvider)"),
})
@Entity
@Table(name="USER_CONSENT_PROT_MAPPER")
@IdClass(UserConsentProtocolMapperEntity.Key.class)
public class UserConsentProtocolMapperEntity {
@Id
@ManyToOne(fetch= FetchType.LAZY)
@JoinColumn(name = "USER_CONSENT_ID")
protected UserConsentEntity userConsent;
@Id
@Column(name="PROTOCOL_MAPPER_ID")
protected String protocolMapperId;
public UserConsentEntity getUserConsent() {
return userConsent;
}
public void setUserConsent(UserConsentEntity userConsent) {
this.userConsent = userConsent;
}
public String getProtocolMapperId() {
return protocolMapperId;
}
public void setProtocolMapperId(String protocolMapperId) {
this.protocolMapperId = protocolMapperId;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null) return false;
if (!(o instanceof UserConsentProtocolMapperEntity)) return false;
UserConsentProtocolMapperEntity that = (UserConsentProtocolMapperEntity)o;
Key myKey = new Key(this.userConsent, this.protocolMapperId);
Key hisKey = new Key(that.userConsent, that.protocolMapperId);
return myKey.equals(hisKey);
}
@Override
public int hashCode() {
Key myKey = new Key(this.userConsent, this.protocolMapperId);
return myKey.hashCode();
}
public static class Key implements Serializable {
protected UserConsentEntity userConsent;
protected String protocolMapperId;
public Key() {
}
public Key(UserConsentEntity userConsent, String protocolMapperId) {
this.userConsent = userConsent;
this.protocolMapperId = protocolMapperId;
}
public UserConsentEntity getUserConsent() {
return userConsent;
}
public String getProtocolMapperId() {
return protocolMapperId;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Key key = (Key) o;
if (userConsent != null ? !userConsent.getId().equals(key.userConsent != null ? key.userConsent.getId() : null) : key.userConsent != null) return false;
if (protocolMapperId != null ? !protocolMapperId.equals(key.protocolMapperId) : key.protocolMapperId != null) return false;
return true;
}
@Override
public int hashCode() {
int result = userConsent != null ? userConsent.getId().hashCode() : 0;
result = 31 * result + (protocolMapperId != null ? protocolMapperId.hashCode() : 0);
return result;
}
}
}

View file

@ -1,135 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.models.jpa.entities;
import javax.persistence.Column;
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:mposolda@redhat.com">Marek Posolda</a>
*/
@NamedQueries({
@NamedQuery(name="deleteUserConsentRolesByRealm", query="delete from UserConsentRoleEntity grantedRole where grantedRole.userConsent IN (select consent from UserConsentEntity consent where consent.user IN (select user from UserEntity user where user.realmId = :realmId))"),
@NamedQuery(name="deleteUserConsentRolesByRealmAndLink", query="delete from UserConsentRoleEntity grantedRole where grantedRole.userConsent IN (select consent from UserConsentEntity consent where consent.user IN (select u from UserEntity u where u.realmId=:realmId and u.federationLink=:link))"),
@NamedQuery(name="deleteUserConsentRolesByUser", query="delete from UserConsentRoleEntity grantedRole where grantedRole.userConsent IN (select consent from UserConsentEntity consent where consent.user = :user)"),
@NamedQuery(name="deleteUserConsentRolesByRole", query="delete from UserConsentRoleEntity grantedRole where grantedRole.roleId = :roleId)"),
@NamedQuery(name="deleteUserConsentRolesByClient", query="delete from UserConsentRoleEntity grantedRole where grantedRole.userConsent IN (select consent from UserConsentEntity consent where consent.clientId = :clientId)"),
@NamedQuery(name="deleteUserConsentRolesByExternalClient", query="delete from UserConsentRoleEntity grantedRole where grantedRole.userConsent IN (select consent from UserConsentEntity consent where consent.clientStorageProvider = :clientStorageProvider and consent.externalClientId = :externalClientId)"),
@NamedQuery(name="deleteUserConsentRolesByClientStorageProvider", query="delete from UserConsentRoleEntity grantedRole where grantedRole.userConsent IN (select consent from UserConsentEntity consent where consent.clientStorageProvider = :clientStorageProvider)"),
})
@Entity
@Table(name="USER_CONSENT_ROLE")
@IdClass(UserConsentRoleEntity.Key.class)
public class UserConsentRoleEntity {
@Id
@ManyToOne(fetch= FetchType.LAZY)
@JoinColumn(name = "USER_CONSENT_ID")
protected UserConsentEntity userConsent;
@Id
@Column(name="ROLE_ID")
protected String roleId;
public UserConsentEntity getUserConsent() {
return userConsent;
}
public void setUserConsent(UserConsentEntity userConsent) {
this.userConsent = userConsent;
}
public String getRoleId() {
return roleId;
}
public void setRoleId(String roleId) {
this.roleId = roleId;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null) return false;
if (!(o instanceof UserConsentRoleEntity)) return false;
UserConsentRoleEntity that = (UserConsentRoleEntity)o;
Key myKey = new Key(this.userConsent, this.roleId);
Key hisKey = new Key(that.userConsent, that.roleId);
return myKey.equals(hisKey);
}
@Override
public int hashCode() {
Key myKey = new Key(this.userConsent, this.roleId);
return myKey.hashCode();
}
public static class Key implements Serializable {
protected UserConsentEntity userConsent;
protected String roleId;
public Key() {
}
public Key(UserConsentEntity userConsent, String roleId) {
this.userConsent = userConsent;
this.roleId = roleId;
}
public UserConsentEntity getUserConsent() {
return userConsent;
}
public String getRoleId() {
return roleId;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Key key = (Key) o;
if (userConsent != null ? !userConsent.getId().equals(key.userConsent != null ? key.userConsent.getId() : null) : key.userConsent != null) return false;
if (roleId != null ? !roleId.equals(key.roleId) : key.roleId != null) return false;
return true;
}
@Override
public int hashCode() {
int result = userConsent != null ? userConsent.getId().hashCode() : 0;
result = 31 * result + (roleId != null ? roleId.hashCode() : 0);
return result;
}
}
}

View file

@ -22,6 +22,7 @@ import org.keycloak.component.ComponentModel;
import org.keycloak.credential.CredentialModel;
import org.keycloak.credential.UserCredentialStore;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientScopeModel;
import org.keycloak.models.FederatedIdentityModel;
import org.keycloak.models.GroupModel;
import org.keycloak.models.KeycloakSession;
@ -32,7 +33,6 @@ import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserConsentModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.jpa.entities.UserConsentEntity;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.storage.StorageId;
import org.keycloak.storage.UserStorageProvider;
@ -41,9 +41,8 @@ import org.keycloak.storage.federated.UserFederatedStorageProvider;
import org.keycloak.storage.jpa.entity.BrokerLinkEntity;
import org.keycloak.storage.jpa.entity.FederatedUser;
import org.keycloak.storage.jpa.entity.FederatedUserAttributeEntity;
import org.keycloak.storage.jpa.entity.FederatedUserConsentClientScopeEntity;
import org.keycloak.storage.jpa.entity.FederatedUserConsentEntity;
import org.keycloak.storage.jpa.entity.FederatedUserConsentProtocolMapperEntity;
import org.keycloak.storage.jpa.entity.FederatedUserConsentRoleEntity;
import org.keycloak.storage.jpa.entity.FederatedUserCredentialAttributeEntity;
import org.keycloak.storage.jpa.entity.FederatedUserCredentialEntity;
import org.keycloak.storage.jpa.entity.FederatedUserGroupMembershipEntity;
@ -361,71 +360,41 @@ public class JpaUserFederatedStorageProvider implements
model.setCreatedDate(entity.getCreatedDate());
model.setLastUpdatedDate(entity.getLastUpdatedDate());
Collection<FederatedUserConsentRoleEntity> grantedRoleEntities = entity.getGrantedRoles();
if (grantedRoleEntities != null) {
for (FederatedUserConsentRoleEntity grantedRole : grantedRoleEntities) {
RoleModel grantedRoleModel = realm.getRoleById(grantedRole.getRoleId());
if (grantedRoleModel != null) {
model.addGrantedRole(grantedRoleModel);
Collection<FederatedUserConsentClientScopeEntity> grantedClientScopeEntities = entity.getGrantedClientScopes();
if (grantedClientScopeEntities != null) {
for (FederatedUserConsentClientScopeEntity grantedClientScope : grantedClientScopeEntities) {
ClientScopeModel grantedClientScopeModel = realm.getClientScopeById(grantedClientScope.getScopeId());
if (grantedClientScopeModel != null) {
model.addGrantedClientScope(grantedClientScopeModel);
}
}
}
Collection<FederatedUserConsentProtocolMapperEntity> grantedProtocolMapperEntities = entity.getGrantedProtocolMappers();
if (grantedProtocolMapperEntities != null) {
for (FederatedUserConsentProtocolMapperEntity grantedProtMapper : grantedProtocolMapperEntities) {
ProtocolMapperModel protocolMapper = client.getProtocolMapperById(grantedProtMapper.getProtocolMapperId());
model.addGrantedProtocolMapper(protocolMapper);
}
}
return model;
}
// Update roles and protocolMappers to given consentEntity from the consentModel
private void updateGrantedConsentEntity(FederatedUserConsentEntity consentEntity, UserConsentModel consentModel) {
Collection<FederatedUserConsentProtocolMapperEntity> grantedProtocolMapperEntities = consentEntity.getGrantedProtocolMappers();
Collection<FederatedUserConsentProtocolMapperEntity> mappersToRemove = new HashSet<>(grantedProtocolMapperEntities);
Collection<FederatedUserConsentClientScopeEntity> grantedClientScopeEntities = consentEntity.getGrantedClientScopes();
Collection<FederatedUserConsentClientScopeEntity> scopesToRemove = new HashSet<>(grantedClientScopeEntities);
for (ProtocolMapperModel protocolMapper : consentModel.getGrantedProtocolMappers()) {
FederatedUserConsentProtocolMapperEntity grantedProtocolMapperEntity = new FederatedUserConsentProtocolMapperEntity();
grantedProtocolMapperEntity.setUserConsent(consentEntity);
grantedProtocolMapperEntity.setProtocolMapperId(protocolMapper.getId());
for (ClientScopeModel clientScope : consentModel.getGrantedClientScopes()) {
FederatedUserConsentClientScopeEntity grantedClientScopeEntity = new FederatedUserConsentClientScopeEntity();
grantedClientScopeEntity.setUserConsent(consentEntity);
grantedClientScopeEntity.setScopeId(clientScope.getId());
// Check if it's already there
if (!grantedProtocolMapperEntities.contains(grantedProtocolMapperEntity)) {
em.persist(grantedProtocolMapperEntity);
if (!grantedClientScopeEntities.contains(grantedClientScopeEntity)) {
em.persist(grantedClientScopeEntity);
em.flush();
grantedProtocolMapperEntities.add(grantedProtocolMapperEntity);
grantedClientScopeEntities.add(grantedClientScopeEntity);
} else {
mappersToRemove.remove(grantedProtocolMapperEntity);
scopesToRemove.remove(grantedClientScopeEntity);
}
}
// Those mappers were no longer on consentModel and will be removed
for (FederatedUserConsentProtocolMapperEntity toRemove : mappersToRemove) {
grantedProtocolMapperEntities.remove(toRemove);
em.remove(toRemove);
}
Collection<FederatedUserConsentRoleEntity> grantedRoleEntities = consentEntity.getGrantedRoles();
Set<FederatedUserConsentRoleEntity> rolesToRemove = new HashSet<>(grantedRoleEntities);
for (RoleModel role : consentModel.getGrantedRoles()) {
FederatedUserConsentRoleEntity consentRoleEntity = new FederatedUserConsentRoleEntity();
consentRoleEntity.setUserConsent(consentEntity);
consentRoleEntity.setRoleId(role.getId());
// Check if it's already there
if (!grantedRoleEntities.contains(consentRoleEntity)) {
em.persist(consentRoleEntity);
em.flush();
grantedRoleEntities.add(consentRoleEntity);
} else {
rolesToRemove.remove(consentRoleEntity);
}
}
// Those roles were no longer on consentModel and will be removed
for (FederatedUserConsentRoleEntity toRemove : rolesToRemove) {
grantedRoleEntities.remove(toRemove);
for (FederatedUserConsentClientScopeEntity toRemove : scopesToRemove) {
grantedClientScopeEntities.remove(toRemove);
em.remove(toRemove);
}
@ -804,9 +773,7 @@ public class JpaUserFederatedStorageProvider implements
@Override
public void preRemove(RealmModel realm) {
int num = em.createNamedQuery("deleteFederatedUserConsentRolesByRealm")
.setParameter("realmId", realm.getId()).executeUpdate();
num = em.createNamedQuery("deleteFederatedUserConsentProtMappersByRealm")
int num = em.createNamedQuery("deleteFederatedUserConsentClientScopesByRealm")
.setParameter("realmId", realm.getId()).executeUpdate();
num = em.createNamedQuery("deleteFederatedUserConsentsByRealm")
.setParameter("realmId", realm.getId()).executeUpdate();
@ -831,7 +798,6 @@ public class JpaUserFederatedStorageProvider implements
@Override
public void preRemove(RealmModel realm, RoleModel role) {
em.createNamedQuery("deleteFederatedUserRoleMappingsByRole").setParameter("roleId", role.getId()).executeUpdate();
em.createNamedQuery("deleteFederatedUserRoleMappingsByRole").setParameter("roleId", role.getId()).executeUpdate();
}
@Override
@ -843,15 +809,10 @@ public class JpaUserFederatedStorageProvider implements
public void preRemove(RealmModel realm, ClientModel client) {
StorageId clientStorageId = new StorageId(client.getId());
if (clientStorageId.isLocal()) {
em.createNamedQuery("deleteFederatedUserConsentProtMappersByClient").setParameter("clientId", client.getId()).executeUpdate();
em.createNamedQuery("deleteFederatedUserConsentRolesByClient").setParameter("clientId", client.getId()).executeUpdate();
em.createNamedQuery("deleteFederatedUserConsentClientScopesByClient").setParameter("clientId", client.getId()).executeUpdate();
em.createNamedQuery("deleteFederatedUserConsentsByClient").setParameter("clientId", client.getId()).executeUpdate();
} else {
em.createNamedQuery("deleteFederatedUserConsentProtMappersByExternalClient")
.setParameter("clientStorageProvider", clientStorageId.getProviderId())
.setParameter("externalClientId",clientStorageId.getExternalId())
.executeUpdate();
em.createNamedQuery("deleteFederatedUserConsentRolesByExternalClient")
em.createNamedQuery("deleteFederatedUserConsentClientScopesByExternalClient")
.setParameter("clientStorageProvider", clientStorageId.getProviderId())
.setParameter("externalClientId",clientStorageId.getExternalId())
.executeUpdate();
@ -865,8 +826,13 @@ public class JpaUserFederatedStorageProvider implements
@Override
public void preRemove(ProtocolMapperModel protocolMapper) {
em.createNamedQuery("deleteFederatedUserConsentProtMappersByProtocolMapper")
.setParameter("protocolMapperId", protocolMapper.getId())
// No op
}
@Override
public void preRemove(ClientScopeModel clientScope) {
em.createNamedQuery("deleteFederatedUserConsentClientScopesByClientScope")
.setParameter("scopeId", clientScope.getId())
.executeUpdate();
}
@ -880,11 +846,7 @@ public class JpaUserFederatedStorageProvider implements
.setParameter("userId", user.getId())
.setParameter("realmId", realm.getId())
.executeUpdate();
em.createNamedQuery("deleteFederatedUserConsentProtMappersByUser")
.setParameter("userId", user.getId())
.setParameter("realmId", realm.getId())
.executeUpdate();
em.createNamedQuery("deleteFederatedUserConsentRolesByUser")
em.createNamedQuery("deleteFederatedUserConsentClientScopesByUser")
.setParameter("userId", user.getId())
.setParameter("realmId", realm.getId())
.executeUpdate();
@ -929,10 +891,7 @@ public class JpaUserFederatedStorageProvider implements
em.createNamedQuery("deleteFederatedAttributesByStorageProvider")
.setParameter("storageProviderId", model.getId())
.executeUpdate();
em.createNamedQuery("deleteFederatedUserConsentProtMappersByStorageProvider")
.setParameter("storageProviderId", model.getId())
.executeUpdate();
em.createNamedQuery("deleteFederatedUserRoleMappingsByStorageProvider")
em.createNamedQuery("deleteFederatedUserConsentClientScopesByStorageProvider")
.setParameter("storageProviderId", model.getId())
.executeUpdate();
em.createNamedQuery("deleteFederatedUserConsentsByStorageProvider")
@ -957,10 +916,7 @@ public class JpaUserFederatedStorageProvider implements
.setParameter("storageProviderId", model.getId())
.executeUpdate();
} else if (model.getProviderType().equals(ClientStorageProvider.class.getName())) {
em.createNamedQuery("deleteFederatedUserConsentProtMappersByClientStorageProvider")
.setParameter("clientStorageProvider", model.getId())
.executeUpdate();
em.createNamedQuery("deleteFederatedUserConsentRolesByClientStorageProvider")
em.createNamedQuery("deleteFederatedUserConsentClientScopesByClientStorageProvider")
.setParameter("clientStorageProvider", model.getId())
.executeUpdate();
em.createNamedQuery("deleteFederatedUserConsentsByClientStorageProvider")

View file

@ -0,0 +1,135 @@
/*
* Copyright 2017 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.storage.jpa.entity;
import java.io.Serializable;
import javax.persistence.Column;
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;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
@NamedQueries({
@NamedQuery(name="deleteFederatedUserConsentClientScopesByRealm", query="delete from FederatedUserConsentClientScopeEntity grantedScope where grantedScope.userConsent IN (select consent from FederatedUserConsentEntity consent where consent.realmId = :realmId)"),
@NamedQuery(name="deleteFederatedUserConsentClientScopesByUser", query="delete from FederatedUserConsentClientScopeEntity grantedScope where grantedScope.userConsent IN (select consent from FederatedUserConsentEntity consent where consent.userId = :userId and consent.realmId = :realmId)"),
@NamedQuery(name="deleteFederatedUserConsentClientScopesByStorageProvider", query="delete from FederatedUserConsentClientScopeEntity grantedScope where grantedScope.userConsent IN (select consent from FederatedUserConsentEntity consent where consent.storageProviderId = :storageProviderId)"),
@NamedQuery(name="deleteFederatedUserConsentClientScopesByClientScope", query="delete from FederatedUserConsentClientScopeEntity grantedScope where grantedScope.scopeId = :scopeId"),
@NamedQuery(name="deleteFederatedUserConsentClientScopesByClient", query="delete from FederatedUserConsentClientScopeEntity grantedScope where grantedScope.userConsent IN (select consent from FederatedUserConsentEntity consent where consent.clientId = :clientId)"),
@NamedQuery(name="deleteFederatedUserConsentClientScopesByExternalClient", query="delete from FederatedUserConsentClientScopeEntity grantedScope where grantedScope.userConsent IN (select consent from FederatedUserConsentEntity consent where consent.clientStorageProvider = :clientStorageProvider and consent.externalClientId = :externalClientId)"),
@NamedQuery(name="deleteFederatedUserConsentClientScopesByClientStorageProvider", query="delete from FederatedUserConsentClientScopeEntity grantedScope where grantedScope.userConsent IN (select consent from FederatedUserConsentEntity consent where consent.clientStorageProvider = :clientStorageProvider)"),
})
@Entity
@Table(name="FED_USER_CONSENT_CL_SCOPE")
@IdClass(FederatedUserConsentClientScopeEntity.Key.class)
public class FederatedUserConsentClientScopeEntity {
@Id
@ManyToOne(fetch= FetchType.LAZY)
@JoinColumn(name = "USER_CONSENT_ID")
protected FederatedUserConsentEntity userConsent;
@Id
@Column(name="SCOPE_ID")
protected String scopeId;
public FederatedUserConsentEntity getUserConsent() {
return userConsent;
}
public void setUserConsent(FederatedUserConsentEntity userConsent) {
this.userConsent = userConsent;
}
public String getScopeId() {
return scopeId;
}
public void setScopeId(String scopeId) {
this.scopeId = scopeId;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null) return false;
if (!(o instanceof FederatedUserConsentClientScopeEntity)) return false;
FederatedUserConsentClientScopeEntity that = ( FederatedUserConsentClientScopeEntity)o;
FederatedUserConsentClientScopeEntity.Key myKey = new FederatedUserConsentClientScopeEntity.Key(this.userConsent, this.scopeId);
FederatedUserConsentClientScopeEntity.Key hisKey = new FederatedUserConsentClientScopeEntity.Key(that.userConsent, that.scopeId);
return myKey.equals(hisKey);
}
@Override
public int hashCode() {
FederatedUserConsentClientScopeEntity.Key myKey = new FederatedUserConsentClientScopeEntity.Key(this.userConsent, this.scopeId);
return myKey.hashCode();
}
public static class Key implements Serializable {
protected FederatedUserConsentEntity userConsent;
protected String scopeId;
public Key() {
}
public Key(FederatedUserConsentEntity userConsent, String scopeId) {
this.userConsent = userConsent;
this.scopeId = scopeId;
}
public FederatedUserConsentEntity getUserConsent() {
return userConsent;
}
public String getScopeId() {
return scopeId;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
FederatedUserConsentClientScopeEntity.Key key = (FederatedUserConsentClientScopeEntity.Key) o;
if (userConsent != null ? !userConsent.getId().equals(key.userConsent != null ? key.userConsent.getId() : null) : key.userConsent != null) return false;
if (scopeId != null ? !scopeId.equals(key.scopeId) : key.scopeId != null) return false;
return true;
}
@Override
public int hashCode() {
int result = userConsent != null ? userConsent.getId().hashCode() : 0;
result = 31 * result + (scopeId != null ? scopeId.hashCode() : 0);
return result;
}
}
}

View file

@ -83,10 +83,7 @@ public class FederatedUserConsentEntity {
@OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "userConsent")
Collection<FederatedUserConsentRoleEntity> grantedRoles = new ArrayList<FederatedUserConsentRoleEntity>();
@OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "userConsent")
Collection<FederatedUserConsentProtocolMapperEntity> grantedProtocolMappers = new ArrayList<FederatedUserConsentProtocolMapperEntity>();
Collection<FederatedUserConsentClientScopeEntity> grantedClientScopes = new ArrayList<>();
public String getId() {
return id;
@ -144,20 +141,12 @@ public class FederatedUserConsentEntity {
this.externalClientId = externalClientId;
}
public Collection<FederatedUserConsentRoleEntity> getGrantedRoles() {
return grantedRoles;
public Collection<FederatedUserConsentClientScopeEntity> getGrantedClientScopes() {
return grantedClientScopes;
}
public void setGrantedRoles(Collection<FederatedUserConsentRoleEntity> grantedRoles) {
this.grantedRoles = grantedRoles;
}
public Collection<FederatedUserConsentProtocolMapperEntity> getGrantedProtocolMappers() {
return grantedProtocolMappers;
}
public void setGrantedProtocolMappers(Collection<FederatedUserConsentProtocolMapperEntity> grantedProtocolMappers) {
this.grantedProtocolMappers = grantedProtocolMappers;
public void setGrantedClientScopes(Collection<FederatedUserConsentClientScopeEntity> grantedClientScopes) {
this.grantedClientScopes = grantedClientScopes;
}
public Long getCreatedDate() {

View file

@ -1,137 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.storage.jpa.entity;
import javax.persistence.Column;
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:mposolda@redhat.com">Marek Posolda</a>
*/
@NamedQueries({
@NamedQuery(name="deleteFederatedUserConsentProtMappersByRealm", query=
"delete from FederatedUserConsentProtocolMapperEntity csm where csm.userConsent IN (select consent from FederatedUserConsentEntity consent where consent.realmId = :realmId)"),
@NamedQuery(name="deleteFederatedUserConsentProtMappersByUser", query="delete from FederatedUserConsentProtocolMapperEntity csm where csm.userConsent IN (select consent from FederatedUserConsentEntity consent where consent.userId = :userId and consent.realmId = :realmId)"),
@NamedQuery(name="deleteFederatedUserConsentProtMappersByStorageProvider", query="delete from FederatedUserConsentProtocolMapperEntity csm where csm.userConsent IN (select consent from FederatedUserConsentEntity consent where consent.storageProviderId = :storageProviderId)"),
@NamedQuery(name="deleteFederatedUserConsentProtMappersByProtocolMapper", query="delete from FederatedUserConsentProtocolMapperEntity csm where csm.protocolMapperId = :protocolMapperId"),
@NamedQuery(name="deleteFederatedUserConsentProtMappersByClient", query="delete from FederatedUserConsentProtocolMapperEntity csm where csm.userConsent IN (select consent from FederatedUserConsentEntity consent where consent.clientId = :clientId)"),
@NamedQuery(name="deleteFederatedUserConsentProtMappersByExternalClient", query="delete from FederatedUserConsentProtocolMapperEntity csm where csm.userConsent IN (select consent from FederatedUserConsentEntity consent where consent.clientStorageProvider = :clientStorageProvider and consent.externalClientId = :externalClientId)"),
@NamedQuery(name="deleteFederatedUserConsentProtMappersByClientStorageProvider", query="delete from FederatedUserConsentProtocolMapperEntity csm where csm.userConsent IN (select consent from FederatedUserConsentEntity consent where consent.clientStorageProvider = :clientStorageProvider)"),
})
@Entity
@Table(name="FED_USER_CONSENT_PROT_MAPPER")
@IdClass(FederatedUserConsentProtocolMapperEntity.Key.class)
public class FederatedUserConsentProtocolMapperEntity {
@Id
@ManyToOne(fetch= FetchType.LAZY)
@JoinColumn(name = "USER_CONSENT_ID")
protected FederatedUserConsentEntity userConsent;
@Id
@Column(name="PROTOCOL_MAPPER_ID")
protected String protocolMapperId;
public FederatedUserConsentEntity getUserConsent() {
return userConsent;
}
public void setUserConsent(FederatedUserConsentEntity userConsent) {
this.userConsent = userConsent;
}
public String getProtocolMapperId() {
return protocolMapperId;
}
public void setProtocolMapperId(String protocolMapperId) {
this.protocolMapperId = protocolMapperId;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null) return false;
if (!(o instanceof FederatedUserConsentProtocolMapperEntity)) return false;
FederatedUserConsentProtocolMapperEntity that = (FederatedUserConsentProtocolMapperEntity)o;
Key myKey = new Key(this.userConsent, this.protocolMapperId);
Key hisKey = new Key(that.userConsent, that.protocolMapperId);
return myKey.equals(hisKey);
}
@Override
public int hashCode() {
Key myKey = new Key(this.userConsent, this.protocolMapperId);
return myKey.hashCode();
}
public static class Key implements Serializable {
protected FederatedUserConsentEntity userConsent;
protected String protocolMapperId;
public Key() {
}
public Key(FederatedUserConsentEntity userConsent, String protocolMapperId) {
this.userConsent = userConsent;
this.protocolMapperId = protocolMapperId;
}
public FederatedUserConsentEntity getUserConsent() {
return userConsent;
}
public String getProtocolMapperId() {
return protocolMapperId;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Key key = (Key) o;
if (userConsent != null ? !userConsent.getId().equals(key.userConsent != null ? key.userConsent.getId() : null) : key.userConsent != null) return false;
if (protocolMapperId != null ? !protocolMapperId.equals(key.protocolMapperId) : key.protocolMapperId != null) return false;
return true;
}
@Override
public int hashCode() {
int result = userConsent != null ? userConsent.getId().hashCode() : 0;
result = 31 * result + (protocolMapperId != null ? protocolMapperId.hashCode() : 0);
return result;
}
}
}

View file

@ -1,135 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.storage.jpa.entity;
import javax.persistence.Column;
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:mposolda@redhat.com">Marek Posolda</a>
*/
@NamedQueries({
@NamedQuery(name="deleteFederatedUserConsentRolesByRealm", query="delete from FederatedUserConsentRoleEntity grantedRole where grantedRole.userConsent IN (select consent from FederatedUserConsentEntity consent where consent.realmId = :realmId)"),
@NamedQuery(name="deleteFederatedUserConsentRolesByUser", query="delete from FederatedUserConsentRoleEntity grantedRole where grantedRole.userConsent IN (select consent from FederatedUserConsentEntity consent where consent.userId = :userId and consent.realmId = :realmId)"),
@NamedQuery(name="deleteFederatedUserConsentRolesByStorageProvider", query="delete from FederatedUserConsentRoleEntity grantedRole where grantedRole.userConsent IN (select consent from FederatedUserConsentEntity consent where consent.storageProviderId = :storageProviderId)"),
@NamedQuery(name="deleteFederatedUserConsentRolesByRole", query="delete from FederatedUserConsentRoleEntity grantedRole where grantedRole.roleId = :roleId"),
@NamedQuery(name="deleteFederatedUserConsentRolesByClient", query="delete from FederatedUserConsentRoleEntity grantedRole where grantedRole.userConsent IN (select consent from FederatedUserConsentEntity consent where consent.clientId = :clientId)"),
@NamedQuery(name="deleteFederatedUserConsentRolesByExternalClient", query="delete from FederatedUserConsentRoleEntity grantedRole where grantedRole.userConsent IN (select consent from FederatedUserConsentEntity consent where consent.clientStorageProvider = :clientStorageProvider and consent.externalClientId = :externalClientId)"),
@NamedQuery(name="deleteFederatedUserConsentRolesByClientStorageProvider", query="delete from FederatedUserConsentRoleEntity grantedRole where grantedRole.userConsent IN (select consent from FederatedUserConsentEntity consent where consent.clientStorageProvider = :clientStorageProvider)"),
})
@Entity
@Table(name="FED_USER_CONSENT_ROLE")
@IdClass(FederatedUserConsentRoleEntity.Key.class)
public class FederatedUserConsentRoleEntity {
@Id
@ManyToOne(fetch= FetchType.LAZY)
@JoinColumn(name = "USER_CONSENT_ID")
protected FederatedUserConsentEntity userConsent;
@Id
@Column(name="ROLE_ID")
protected String roleId;
public FederatedUserConsentEntity getUserConsent() {
return userConsent;
}
public void setUserConsent(FederatedUserConsentEntity userConsent) {
this.userConsent = userConsent;
}
public String getRoleId() {
return roleId;
}
public void setRoleId(String roleId) {
this.roleId = roleId;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null) return false;
if (!(o instanceof FederatedUserConsentRoleEntity)) return false;
FederatedUserConsentRoleEntity that = (FederatedUserConsentRoleEntity)o;
Key myKey = new Key(this.userConsent, this.roleId);
Key hisKey = new Key(that.userConsent, that.roleId);
return myKey.equals(hisKey);
}
@Override
public int hashCode() {
Key myKey = new Key(this.userConsent, this.roleId);
return myKey.hashCode();
}
public static class Key implements Serializable {
protected FederatedUserConsentEntity userConsent;
protected String roleId;
public Key() {
}
public Key(FederatedUserConsentEntity userConsent, String roleId) {
this.userConsent = userConsent;
this.roleId = roleId;
}
public FederatedUserConsentEntity getUserConsent() {
return userConsent;
}
public String getRoleId() {
return roleId;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Key key = (Key) o;
if (userConsent != null ? !userConsent.getId().equals(key.userConsent != null ? key.userConsent.getId() : null) : key.userConsent != null) return false;
if (roleId != null ? !roleId.equals(key.roleId) : key.roleId != null) return false;
return true;
}
@Override
public int hashCode() {
int result = userConsent != null ? userConsent.getId().hashCode() : 0;
result = 31 * result + (roleId != null ? roleId.hashCode() : 0);
return result;
}
}
}

View file

@ -84,4 +84,184 @@
<addPrimaryKey columnNames="USER_SESSION_ID,CLIENT_ID, CLIENT_STORAGE_PROVIDER, EXTERNAL_CLIENT_ID, OFFLINE_FLAG" constraintName="CONSTRAINT_OFFL_CL_SES_PK3" tableName="OFFLINE_CLIENT_SESSION"/>
</changeSet>
<changeSet author="mposolda@redhat.com" id="4.0.0-KEYCLOAK-5579">
<!-- 1 - Rename clientTemplate to clientScope and drop some unused things from clientTemplate -->
<dropForeignKeyConstraint baseTableName="CLIENT_TEMPLATE_ATTRIBUTES" constraintName="FK_CL_TEMPL_ATTR_TEMPL" />
<renameTable oldTableName="CLIENT_TEMPLATE_ATTRIBUTES" newTableName="CLIENT_SCOPE_ATTRIBUTES" />
<renameColumn tableName="CLIENT_SCOPE_ATTRIBUTES" newColumnName="SCOPE_ID" oldColumnName="TEMPLATE_ID" columnDataType="VARCHAR(36)" />
<dropForeignKeyConstraint baseTableName="TEMPLATE_SCOPE_MAPPING" constraintName="FK_TEMPL_SCOPE_TEMPL" />
<dropForeignKeyConstraint baseTableName="TEMPLATE_SCOPE_MAPPING" constraintName="FK_TEMPL_SCOPE_ROLE" />
<renameTable oldTableName="TEMPLATE_SCOPE_MAPPING" newTableName="CLIENT_SCOPE_ROLE_MAPPING" />
<renameColumn tableName="CLIENT_SCOPE_ROLE_MAPPING" newColumnName="SCOPE_ID" oldColumnName="TEMPLATE_ID" columnDataType="VARCHAR(36)" />
<dropForeignKeyConstraint baseTableName="CLIENT" constraintName="FK_CLI_TMPLT_CLIENT" />
<dropForeignKeyConstraint baseTableName="PROTOCOL_MAPPER" constraintName="FK_CLI_TMPLT_MAPPER" />
<renameColumn tableName="PROTOCOL_MAPPER" newColumnName="CLIENT_SCOPE_ID" oldColumnName="CLIENT_TEMPLATE_ID" columnDataType="VARCHAR(36)" />
<dropForeignKeyConstraint baseTableName="CLIENT_TEMPLATE" constraintName="FK_REALM_CLI_TMPLT" />
<dropUniqueConstraint constraintName="UK_CLI_TEMPLATE" tableName="CLIENT_TEMPLATE"/>
<dropDefaultValue tableName="CLIENT_TEMPLATE" columnName="FULL_SCOPE_ALLOWED" />
<dropDefaultValue tableName="CLIENT_TEMPLATE" columnName="CONSENT_REQUIRED" />
<dropDefaultValue tableName="CLIENT_TEMPLATE" columnName="STANDARD_FLOW_ENABLED" />
<dropDefaultValue tableName="CLIENT_TEMPLATE" columnName="IMPLICIT_FLOW_ENABLED" />
<dropDefaultValue tableName="CLIENT_TEMPLATE" columnName="DIRECT_ACCESS_GRANTS_ENABLED" />
<dropDefaultValue tableName="CLIENT_TEMPLATE" columnName="SERVICE_ACCOUNTS_ENABLED" />
<dropDefaultValue tableName="CLIENT_TEMPLATE" columnName="FRONTCHANNEL_LOGOUT" />
<dropDefaultValue tableName="CLIENT_TEMPLATE" columnName="BEARER_ONLY" />
<dropDefaultValue tableName="CLIENT_TEMPLATE" columnName="PUBLIC_CLIENT" />
<dropIndex tableName="CLIENT_SCOPE_ROLE_MAPPING" indexName="IDX_TEMPL_SCOPE_MAPP_ROLE" />
<dropIndex tableName="PROTOCOL_MAPPER" indexName="IDX_PROTO_MAPP_CLIENT_TEMPL" />
<dropIndex tableName="CLIENT" indexName="IDX_CLIENT_CLIENT_TEMPL_ID" />
<dropColumn tableName="CLIENT_TEMPLATE" columnName="FULL_SCOPE_ALLOWED" />
<dropColumn tableName="CLIENT_TEMPLATE" columnName="CONSENT_REQUIRED" />
<dropColumn tableName="CLIENT_TEMPLATE" columnName="STANDARD_FLOW_ENABLED" />
<dropColumn tableName="CLIENT_TEMPLATE" columnName="IMPLICIT_FLOW_ENABLED" />
<dropColumn tableName="CLIENT_TEMPLATE" columnName="DIRECT_ACCESS_GRANTS_ENABLED" />
<dropColumn tableName="CLIENT_TEMPLATE" columnName="SERVICE_ACCOUNTS_ENABLED" />
<dropColumn tableName="CLIENT_TEMPLATE" columnName="FRONTCHANNEL_LOGOUT" />
<dropColumn tableName="CLIENT_TEMPLATE" columnName="BEARER_ONLY" />
<dropColumn tableName="CLIENT_TEMPLATE" columnName="PUBLIC_CLIENT" />
<renameTable oldTableName="CLIENT_TEMPLATE" newTableName="CLIENT_SCOPE" />
<addUniqueConstraint columnNames="REALM_ID,NAME" constraintName="UK_CLI_SCOPE" tableName="CLIENT_SCOPE"/>
<addForeignKeyConstraint baseColumnNames="REALM_ID" baseTableName="CLIENT_SCOPE"
constraintName="FK_REALM_CLI_SCOPE" referencedColumnNames="ID" referencedTableName="REALM"/>
<addForeignKeyConstraint baseColumnNames="CLIENT_SCOPE_ID" baseTableName="PROTOCOL_MAPPER"
constraintName="FK_CLI_SCOPE_MAPPER" referencedColumnNames="ID" referencedTableName="CLIENT_SCOPE"/>
<addForeignKeyConstraint baseColumnNames="SCOPE_ID" baseTableName="CLIENT_SCOPE_ROLE_MAPPING"
constraintName="FK_CL_SCOPE_RM_SCOPE" referencedColumnNames="ID" referencedTableName="CLIENT_SCOPE"/>
<addForeignKeyConstraint baseColumnNames="ROLE_ID" baseTableName="CLIENT_SCOPE_ROLE_MAPPING"
constraintName="FK_CL_SCOPE_RM_ROLE" referencedColumnNames="ID" referencedTableName="KEYCLOAK_ROLE"/>
<addForeignKeyConstraint baseTableName="CLIENT_SCOPE_ATTRIBUTES" baseColumnNames="SCOPE_ID"
constraintName="FK_CL_SCOPE_ATTR_SCOPE" referencedTableName="CLIENT_SCOPE" referencedColumnNames="ID" />
<!-- 2 - Client binding to more clientScopes -->
<!-- Foreign key dropped above TODO:mposolda migration existing clientTemplate to default clientScope -->
<dropColumn tableName="CLIENT" columnName="CLIENT_TEMPLATE_ID" />
<dropDefaultValue tableName="CLIENT" columnName="USE_TEMPLATE_CONFIG"/>
<dropDefaultValue tableName="CLIENT" columnName="USE_TEMPLATE_SCOPE" />
<dropDefaultValue tableName="CLIENT" columnName="USE_TEMPLATE_MAPPERS" />
<dropColumn tableName="CLIENT" columnName="USE_TEMPLATE_CONFIG" />
<dropColumn tableName="CLIENT" columnName="USE_TEMPLATE_SCOPE" />
<dropColumn tableName="CLIENT" columnName="USE_TEMPLATE_MAPPERS" />
<createTable tableName="CLIENT_SCOPE_CLIENT">
<column name="CLIENT_ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
<column name="SCOPE_ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
<column name="DEFAULT_SCOPE" type="BOOLEAN" defaultValueBoolean="false">
<constraints nullable="false"/>
</column>
</createTable>
<addPrimaryKey columnNames="CLIENT_ID, SCOPE_ID" constraintName="C_CLI_SCOPE_BIND" tableName="CLIENT_SCOPE_CLIENT"/>
<addForeignKeyConstraint baseColumnNames="CLIENT_ID" baseTableName="CLIENT_SCOPE_CLIENT" constraintName="FK_C_CLI_SCOPE_CLIENT" referencedColumnNames="ID" referencedTableName="CLIENT"/>
<addForeignKeyConstraint baseColumnNames="SCOPE_ID" baseTableName="CLIENT_SCOPE_CLIENT" constraintName="FK_C_CLI_SCOPE_SCOPE" referencedColumnNames="ID" referencedTableName="CLIENT_SCOPE"/>
<!-- Default client scopes (global scopes configured at realm level) -->
<createTable tableName="DEFAULT_CLIENT_SCOPE">
<column name="REALM_ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
<column name="SCOPE_ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
<column name="DEFAULT_SCOPE" type="BOOLEAN" defaultValueBoolean="false">
<constraints nullable="false"/>
</column>
</createTable>
<addPrimaryKey columnNames="REALM_ID, SCOPE_ID" constraintName="R_DEF_CLI_SCOPE_BIND" tableName="DEFAULT_CLIENT_SCOPE"/>
<addForeignKeyConstraint baseColumnNames="REALM_ID" baseTableName="DEFAULT_CLIENT_SCOPE" constraintName="FK_R_DEF_CLI_SCOPE_REALM" referencedColumnNames="ID" referencedTableName="REALM"/>
<addForeignKeyConstraint baseColumnNames="SCOPE_ID" baseTableName="DEFAULT_CLIENT_SCOPE" constraintName="FK_R_DEF_CLI_SCOPE_SCOPE" referencedColumnNames="ID" referencedTableName="CLIENT_SCOPE"/>
<!-- Remove scopeParamRequired -->
<dropDefaultValue tableName="KEYCLOAK_ROLE" columnName="SCOPE_PARAM_REQUIRED" />
<dropColumn tableName="KEYCLOAK_ROLE" columnName="SCOPE_PARAM_REQUIRED" />
<!-- Drop consent stuff from protocolMappers table -->
<dropDefaultValue tableName="PROTOCOL_MAPPER" columnName="CONSENT_REQUIRED" />
<dropColumn tableName="PROTOCOL_MAPPER" columnName="CONSENT_REQUIRED" />
<dropColumn tableName="PROTOCOL_MAPPER" columnName="CONSENT_TEXT" />
<!-- Consents related changes -->
<dropForeignKeyConstraint baseTableName="USER_CONSENT_ROLE" constraintName="FK_GRNTCSNT_ROLE_GR" />
<dropTable tableName="USER_CONSENT_ROLE" />
<dropForeignKeyConstraint baseTableName="USER_CONSENT_PROT_MAPPER" constraintName="FK_GRNTCSNT_PRM_GR" />
<dropTable tableName="USER_CONSENT_PROT_MAPPER" />
<createTable tableName="USER_CONSENT_CLIENT_SCOPE">
<column name="USER_CONSENT_ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
<column name="SCOPE_ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
</createTable>
<addPrimaryKey columnNames="USER_CONSENT_ID, SCOPE_ID" constraintName="CONSTRAINT_GRNTCSNT_CLSC_PM" tableName="USER_CONSENT_CLIENT_SCOPE"/>
<addForeignKeyConstraint baseColumnNames="USER_CONSENT_ID" baseTableName="USER_CONSENT_CLIENT_SCOPE" constraintName="FK_GRNTCSNT_CLSC_USC" referencedColumnNames="ID" referencedTableName="USER_CONSENT"/>
<!-- Federated consents related changes -->
<dropTable tableName="FED_USER_CONSENT_ROLE" />
<dropTable tableName="FED_USER_CONSENT_PROT_MAPPER" />
<createTable tableName="FED_USER_CONSENT_CL_SCOPE">
<column name="USER_CONSENT_ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
<column name="SCOPE_ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
</createTable>
<addPrimaryKey columnNames="USER_CONSENT_ID, SCOPE_ID" constraintName="CONSTRAINT_FGRNTCSNT_CLSC_PM" tableName="FED_USER_CONSENT_CL_SCOPE"/>
<!-- Indexes for foreign keys -->
<createIndex indexName="IDX_REALM_CLSCOPE" tableName="CLIENT_SCOPE">
<column name="REALM_ID" type="VARCHAR(36)"/>
</createIndex>
<createIndex indexName="IDX_CLSCOPE_PROTMAP" tableName="PROTOCOL_MAPPER">
<column name="CLIENT_SCOPE_ID" type="VARCHAR(36)"/>
</createIndex>
<createIndex indexName="IDX_CLSCOPE_ROLE" tableName="CLIENT_SCOPE_ROLE_MAPPING">
<column name="SCOPE_ID" type="VARCHAR(36)"/>
</createIndex>
<createIndex indexName="IDX_ROLE_CLSCOPE" tableName="CLIENT_SCOPE_ROLE_MAPPING">
<column name="ROLE_ID" type="VARCHAR(36)"/>
</createIndex>
<createIndex indexName="IDX_CLSCOPE_ATTRS" tableName="CLIENT_SCOPE_ATTRIBUTES">
<column name="SCOPE_ID" type="VARCHAR(36)"/>
</createIndex>
<createIndex indexName="IDX_CLSCOPE_CL" tableName="CLIENT_SCOPE_CLIENT">
<column name="CLIENT_ID" type="VARCHAR(36)"/>
</createIndex>
<createIndex indexName="IDX_CL_CLSCOPE" tableName="CLIENT_SCOPE_CLIENT">
<column name="SCOPE_ID" type="VARCHAR(36)"/>
</createIndex>
<createIndex indexName="IDX_DEFCLS_REALM" tableName="DEFAULT_CLIENT_SCOPE">
<column name="REALM_ID" type="VARCHAR(36)"/>
</createIndex>
<createIndex indexName="IDX_DEFCLS_SCOPE" tableName="DEFAULT_CLIENT_SCOPE">
<column name="SCOPE_ID" type="VARCHAR(36)"/>
</createIndex>
<createIndex indexName="IDX_USCONSENT_CLSCOPE" tableName="USER_CONSENT_CLIENT_SCOPE">
<column name="USER_CONSENT_ID" type="VARCHAR(36)"/>
</createIndex>
</changeSet>
</databaseChangeLog>

View file

@ -41,8 +41,7 @@
<class>org.keycloak.models.jpa.entities.IdentityProviderMapperEntity</class>
<class>org.keycloak.models.jpa.entities.ProtocolMapperEntity</class>
<class>org.keycloak.models.jpa.entities.UserConsentEntity</class>
<class>org.keycloak.models.jpa.entities.UserConsentRoleEntity</class>
<class>org.keycloak.models.jpa.entities.UserConsentProtocolMapperEntity</class>
<class>org.keycloak.models.jpa.entities.UserConsentClientScopeEntity</class>
<class>org.keycloak.models.jpa.entities.AuthenticationFlowEntity</class>
<class>org.keycloak.models.jpa.entities.AuthenticationExecutionEntity</class>
<class>org.keycloak.models.jpa.entities.AuthenticatorConfigEntity</class>
@ -53,8 +52,10 @@
<class>org.keycloak.models.jpa.entities.GroupAttributeEntity</class>
<class>org.keycloak.models.jpa.entities.GroupRoleMappingEntity</class>
<class>org.keycloak.models.jpa.entities.UserGroupMembershipEntity</class>
<class>org.keycloak.models.jpa.entities.ClientTemplateEntity</class>
<class>org.keycloak.models.jpa.entities.TemplateScopeMappingEntity</class>
<class>org.keycloak.models.jpa.entities.ClientScopeEntity</class>
<class>org.keycloak.models.jpa.entities.ClientScopeRoleMappingEntity</class>
<class>org.keycloak.models.jpa.entities.ClientScopeClientMappingEntity</class>
<class>org.keycloak.models.jpa.entities.DefaultClientScopeRealmMappingEntity</class>
<class>org.keycloak.models.jpa.entities.ClientInitialAccessEntity</class>
<!-- JpaAuditProviders -->
@ -74,8 +75,7 @@
<class>org.keycloak.storage.jpa.entity.FederatedUser</class>
<class>org.keycloak.storage.jpa.entity.FederatedUserAttributeEntity</class>
<class>org.keycloak.storage.jpa.entity.FederatedUserConsentEntity</class>
<class>org.keycloak.storage.jpa.entity.FederatedUserConsentRoleEntity</class>
<class>org.keycloak.storage.jpa.entity.FederatedUserConsentProtocolMapperEntity</class>
<class>org.keycloak.storage.jpa.entity.FederatedUserConsentClientScopeEntity</class>
<class>org.keycloak.storage.jpa.entity.FederatedUserCredentialEntity</class>
<class>org.keycloak.storage.jpa.entity.FederatedUserCredentialAttributeEntity</class>
<class>org.keycloak.storage.jpa.entity.FederatedUserGroupMembershipEntity</class>

View file

@ -47,6 +47,7 @@ public interface Details {
String REASON = "reason";
String REVOKED_CLIENT = "revoked_client";
String AUDIENCE = "audience";
String SCOPE = "scope";
String REQUESTED_ISSUER = "requested_issuer";
String REQUESTED_SUBJECT = "requested_subject";
String CLIENT_SESSION_STATE = "client_session_state";

View file

@ -141,7 +141,7 @@ public enum ResourceType {
/**
*
*/
, CLIENT_TEMPLATE
, CLIENT_SCOPE
/**
*

View file

@ -17,6 +17,7 @@
package org.keycloak.forms.login;
import org.keycloak.models.ClientScopeModel;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserModel;
@ -84,8 +85,7 @@ public interface LoginFormsProvider extends Provider {
LoginFormsProvider setClientSessionCode(String accessCode);
LoginFormsProvider setAccessRequest(List<RoleModel> realmRolesRequested, MultivaluedMap<String,RoleModel> resourceRolesRequested, List<ProtocolMapperModel> protocolMappers);
LoginFormsProvider setAccessRequest(String message);
LoginFormsProvider setAccessRequest(List<ClientScopeModel> clientScopesRequested);
/**
* Set one global error message.

View file

@ -38,6 +38,7 @@ import org.keycloak.migration.migrators.MigrateTo3_2_0;
import org.keycloak.migration.migrators.MigrateTo3_4_0;
import org.keycloak.migration.migrators.MigrateTo3_4_1;
import org.keycloak.migration.migrators.MigrateTo3_4_2;
import org.keycloak.migration.migrators.MigrateTo4_0_0;
import org.keycloak.migration.migrators.Migration;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
@ -70,7 +71,8 @@ public class MigrationModelManager {
new MigrateTo3_2_0(),
new MigrateTo3_4_0(),
new MigrateTo3_4_1(),
new MigrateTo3_4_2()
new MigrateTo3_4_2(),
new MigrateTo4_0_0()
};
public static void migrate(KeycloakSession session) {

View file

@ -23,6 +23,7 @@ import org.keycloak.provider.Provider;
import org.keycloak.representations.idm.ProtocolMapperRepresentation;
import java.util.List;
import java.util.Map;
/**
* Various common utils needed for migration from older version to newer
@ -37,7 +38,7 @@ public interface MigrationProvider extends Provider {
*/
List<ProtocolMapperRepresentation> getMappersForClaimMask(Long claimMask);
List<ProtocolMapperModel> getBuiltinMappers(String protocol);
Map<String, ProtocolMapperModel> getBuiltinMappers(String protocol);
void setupAdminCli(RealmModel realm);

View file

@ -53,7 +53,6 @@ public class MigrateTo1_2_0 implements Migration {
if (roleModel != null) continue;
roleModel = client.addRole(role);
roleModel.setDescription("${role_" + role.toLowerCase().replaceAll("_", "-") + "}");
roleModel.setScopeParamRequired(false);
}
}
}

View file

@ -45,13 +45,7 @@ public class MigrateTo1_6_0 implements Migration {
public void migrate(KeycloakSession session) {
MigrationProvider provider = session.getProvider(MigrationProvider.class);
List<ProtocolMapperModel> builtinMappers = provider.getBuiltinMappers("openid-connect");
ProtocolMapperModel localeMapper = null;
for (ProtocolMapperModel m : builtinMappers) {
if (m.getName().equals("locale")) {
localeMapper = m;
}
}
ProtocolMapperModel localeMapper = provider.getBuiltinMappers("openid-connect").get("locale");
if (localeMapper == null) {
throw new RuntimeException("Can't find default locale mapper");
@ -66,13 +60,8 @@ public class MigrateTo1_6_0 implements Migration {
@Override
public void migrateImport(KeycloakSession session, RealmModel realm, RealmRepresentation rep, boolean skipUserDependent) {
MigrationProvider provider = session.getProvider(MigrationProvider.class);
List<ProtocolMapperModel> builtinMappers = provider.getBuiltinMappers("openid-connect");
ProtocolMapperModel localeMapper = null;
for (ProtocolMapperModel m : builtinMappers) {
if (m.getName().equals("locale")) {
localeMapper = m;
}
}
ProtocolMapperModel localeMapper = provider.getBuiltinMappers("openid-connect").get("locale");
if (localeMapper == null) {
throw new RuntimeException("Can't find default locale mapper");
}
@ -85,16 +74,7 @@ public class MigrateTo1_6_0 implements Migration {
realm.setOfflineSessionIdleTimeout(Constants.DEFAULT_OFFLINE_SESSION_IDLE_TIMEOUT);
if (realm.getRole(Constants.OFFLINE_ACCESS_ROLE) == null) {
for (RoleModel realmRole : realm.getRoles()) {
realmRole.setScopeParamRequired(false);
}
for (ClientModel client : realm.getClients()) {
for (RoleModel clientRole : client.getRoles()) {
clientRole.setScopeParamRequired(false);
}
}
KeycloakModelUtils.setupOfflineTokens(realm);
KeycloakModelUtils.setupOfflineRole(realm);
RoleModel role = realm.getRole(Constants.OFFLINE_ACCESS_ROLE);
// Bulk grant of offline_access role to all users
@ -110,7 +90,6 @@ public class MigrateTo1_6_0 implements Migration {
if (client.getRole(AdminRoles.CREATE_CLIENT) == null) {
RoleModel role = client.addRole(AdminRoles.CREATE_CLIENT);
role.setDescription("${role_" + AdminRoles.CREATE_CLIENT + "}");
role.setScopeParamRequired(false);
client.getRealm().getRole(AdminRoles.ADMIN).addCompositeRole(role);
}
@ -120,8 +99,6 @@ public class MigrateTo1_6_0 implements Migration {
if (client.getRole(AdminRoles.CREATE_CLIENT) == null) {
RoleModel role = client.addRole(AdminRoles.CREATE_CLIENT);
role.setDescription("${role_" + AdminRoles.CREATE_CLIENT + "}");
role.setScopeParamRequired(false);
client.getRole(AdminRoles.REALM_ADMIN).addCompositeRole(role);
}
}

View file

@ -20,7 +20,7 @@ package org.keycloak.migration.migrators;
import org.keycloak.migration.ModelVersion;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientTemplateModel;
import org.keycloak.models.ClientScopeModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.representations.idm.RealmRepresentation;
@ -44,8 +44,8 @@ public class MigrateTo2_3_0 implements Migration {
MigrationUtils.updateProtocolMappers(client);
}
for (ClientTemplateModel clientTemplate : realm.getClientTemplates()) {
MigrationUtils.updateProtocolMappers(clientTemplate);
for (ClientScopeModel clientScope : realm.getClientScopes()) {
MigrationUtils.updateProtocolMappers(clientScope);
}
}

View file

@ -19,8 +19,6 @@ package org.keycloak.migration.migrators;
import org.keycloak.migration.ModelVersion;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientTemplateModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.utils.DefaultKeyProviders;

View file

@ -0,0 +1,133 @@
/*
* Copyright 2017 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.migration.migrators;
import java.util.List;
import org.jboss.logging.Logger;
import org.keycloak.OAuth2Constants;
import org.keycloak.component.ComponentModel;
import org.keycloak.migration.ModelVersion;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientScopeModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.utils.DefaultClientScopes;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.representations.idm.RealmRepresentation;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class MigrateTo4_0_0 implements Migration {
public static final ModelVersion VERSION = new ModelVersion("4.0.0");
private static final Logger LOG = Logger.getLogger(MigrateTo4_0_0.class);
@Override
public ModelVersion getVersion() {
return VERSION;
}
@Override
public void migrate(KeycloakSession session) {
session.realms().getRealms().stream().forEach(
r -> {
migrateRealm(session, r, false);
}
);
}
@Override
public void migrateImport(KeycloakSession session, RealmModel realm, RealmRepresentation rep, boolean skipUserDependent) {
migrateRealm(session, realm, true);
}
protected void migrateRealm(KeycloakSession session, RealmModel realm, boolean json) {
// Upgrade names of clientScopes to not contain space
for (ClientScopeModel clientScope : realm.getClientScopes()) {
if (clientScope.getName().contains(" ")) {
LOG.debugf("Replacing spaces with underscores in the name of client scope '%s' of realm '%s'", clientScope.getName(), realm.getName());
String replacedName = clientScope.getName().replaceAll(" ", "_");
clientScope.setName(replacedName);
}
}
if (!json) {
// Add default client scopes. But don't add them to existing clients. For JSON, they were already added
LOG.debugf("Adding defaultClientScopes for realm '%s'", realm.getName());
DefaultClientScopes.createDefaultClientScopes(session, realm, false);
}
// Upgrade configuration of "allowed-client-templates" client registration policy
for (ComponentModel component : realm.getComponents(realm.getId(), "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy")) {
if ("allowed-client-templates".equals(component.getProviderId())) {
List<String> configVal = component.getConfig().remove("allowed-client-templates");
if (configVal != null) {
component.getConfig().put("allowed-client-scopes", configVal);
}
component.put("allow-default-scopes", true);
realm.updateComponent(component);
}
}
// 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;
if (offlineAccessRole == null) {
LOG.infof("Role 'offline_access' not available in realm '%s'. Skip migration of offline_access client scope.", realm.getName());
} else {
offlineAccessScope = KeycloakModelUtils.getClientScopeByName(realm, OAuth2Constants.OFFLINE_ACCESS);
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);
}
}
}
}
}
// 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);
}
}
}
}

View file

@ -17,18 +17,27 @@
package org.keycloak.migration.migrators;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import org.keycloak.Config;
import org.keycloak.OAuth2Constants;
import org.keycloak.OAuthErrorException;
import org.keycloak.models.AdminRoles;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientScopeModel;
import org.keycloak.models.Constants;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ProtocolMapperContainerModel;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RequiredActionProviderModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserConsentModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.utils.KeycloakModelUtils;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
@ -40,7 +49,6 @@ public class MigrationUtils {
if (client != null && client.getRole(roleName) == null) {
RoleModel role = client.addRole(roleName);
role.setDescription("${role_" + roleName + "}");
role.setScopeParamRequired(false);
client.getRealm().getRole(AdminRoles.ADMIN).addCompositeRole(role);
}
@ -50,7 +58,6 @@ public class MigrationUtils {
if (client != null && client.getRole(roleName) == null) {
RoleModel role = client.addRole(roleName);
role.setDescription("${role_" + roleName + "}");
role.setScopeParamRequired(false);
client.getRole(AdminRoles.REALM_ADMIN).addCompositeRole(role);
}
@ -79,4 +86,27 @@ public class MigrationUtils {
}
}
// Called when offline token older than 4.0 (Offline token without clientScopeIds) is called
public static void migrateOldOfflineToken(KeycloakSession session, RealmModel realm, ClientModel client, UserModel user) throws OAuthErrorException {
ClientScopeModel offlineScope = KeycloakModelUtils.getClientScopeByName(realm, OAuth2Constants.OFFLINE_ACCESS);
if (offlineScope == null) {
throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Offline Access scope not found");
}
if (client.isConsentRequired()) {
// Automatically add consents for client and for offline_access. We know that both were defacto approved by user already and offlineSession is still valid
UserConsentModel consent = session.users().getConsentByClient(realm, user.getId(), client.getId());
if (consent != null) {
if (client.isDisplayOnConsentScreen()) {
consent.addGrantedClientScope(client);
}
if (offlineScope.isDisplayOnConsentScreen()) {
consent.addGrantedClientScope(offlineScope);
}
session.users().updateConsent(realm, user.getId(), consent);
}
}
}
}

View file

@ -18,55 +18,35 @@
package org.keycloak.models;
/**
* TODO: remove this class entirely?
*
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class ClientConfigResolver {
protected ClientModel client;
protected ClientTemplateModel clientTemplate;
public ClientConfigResolver(ClientModel client) {
this.client = client;
this.clientTemplate = client.getClientTemplate();
}
public String resolveAttribute(String name) {
if (clientTemplate != null && client.useTemplateConfig()) {
return clientTemplate.getAttribute(name);
} else {
return client.getAttribute(name);
}
return client.getAttribute(name);
}
public boolean isFrontchannelLogout() {
if (clientTemplate != null && client.useTemplateConfig()) {
return clientTemplate.isFrontchannelLogout();
}
return client.isFrontchannelLogout();
}
boolean isConsentRequired() {
if (clientTemplate != null && client.useTemplateConfig()) {
return clientTemplate.isConsentRequired();
}
return client.isConsentRequired();
}
boolean isStandardFlowEnabled() {
if (clientTemplate != null && client.useTemplateConfig()) {
return clientTemplate.isStandardFlowEnabled();
}
return client.isStandardFlowEnabled();
}
boolean isServiceAccountsEnabled() {
if (clientTemplate != null && client.useTemplateConfig()) {
return clientTemplate.isServiceAccountsEnabled();
}
return client.isServiceAccountsEnabled();
}
}

View file

@ -69,4 +69,6 @@ public interface Constants {
String GENERATE = "GENERATE";
int DEFAULT_MAX_RESULTS = 100;
String OFFLINE_ACCESS_SCOPE_CONSENT_TEXT = "${offlineAccessScopeConsentText}";
}

View file

@ -43,7 +43,6 @@ public class ImpersonationConstants {
if (realmAdminApp.getRole(IMPERSONATION_ROLE) != null) return;
RoleModel impersonationRole = realmAdminApp.addRole(IMPERSONATION_ROLE);
impersonationRole.setDescription("${role_" + IMPERSONATION_ROLE + "}");
impersonationRole.setScopeParamRequired(false);
adminRole.addCompositeRole(impersonationRole);
}
@ -54,7 +53,6 @@ public class ImpersonationConstants {
if (realmAdminApp.getRole(IMPERSONATION_ROLE) != null) return;
RoleModel impersonationRole = realmAdminApp.addRole(IMPERSONATION_ROLE);
impersonationRole.setDescription("${role_" + IMPERSONATION_ROLE + "}");
impersonationRole.setScopeParamRequired(false);
RoleModel adminRole = realmAdminApp.getRole(AdminRoles.REALM_ADMIN);
adminRole.addCompositeRole(impersonationRole);
}

View file

@ -30,7 +30,7 @@ public interface CacheRealmProvider extends RealmProvider {
void registerRealmInvalidation(String id, String name);
void registerClientInvalidation(String id, String clientId, String realmId);
void registerClientTemplateInvalidation(String id);
void registerClientScopeInvalidation(String id);
void registerRoleInvalidation(String id, String roleName, String roleContainerId);

View file

@ -48,9 +48,7 @@ public class PersistentAuthenticatedClientSessionAdapter implements Authenticate
data.setAction(clientSession.getAction());
data.setAuthMethod(clientSession.getProtocol());
data.setNotes(clientSession.getNotes());
data.setProtocolMappers(clientSession.getProtocolMappers());
data.setRedirectUri(clientSession.getRedirectUri());
data.setRoles(clientSession.getRoles());
model = new PersistentClientSessionModel();
model.setClientId(clientSession.getClient().getId());
@ -174,26 +172,6 @@ public class PersistentAuthenticatedClientSessionAdapter implements Authenticate
getData().setAction(action);
}
@Override
public Set<String> getRoles() {
return getData().getRoles();
}
@Override
public void setRoles(Set<String> roles) {
getData().setRoles(roles);
}
@Override
public Set<String> getProtocolMappers() {
return getData().getProtocolMappers();
}
@Override
public void setProtocolMappers(Set<String> protocolMappers) {
getData().setProtocolMappers(protocolMappers);
}
@Override
public String getProtocol() {
return getData().getAuthMethod();
@ -256,12 +234,6 @@ public class PersistentAuthenticatedClientSessionAdapter implements Authenticate
@JsonProperty("redirectUri")
private String redirectUri;
@JsonProperty("protocolMappers")
private Set<String> protocolMappers;
@JsonProperty("roles")
private Set<String> roles;
@JsonProperty("notes")
private Map<String, String> notes;
@ -275,6 +247,10 @@ public class PersistentAuthenticatedClientSessionAdapter implements Authenticate
private Map<String, Object> executionStatus;
@JsonProperty("requiredActions")
private Set<String> requiredActions;
@JsonProperty("protocolMappers")
private Set<String> protocolMappers;
@JsonProperty("roles")
private Set<String> roles;
public String getAuthMethod() {
@ -293,22 +269,6 @@ public class PersistentAuthenticatedClientSessionAdapter implements Authenticate
this.redirectUri = redirectUri;
}
public Set<String> getProtocolMappers() {
return protocolMappers;
}
public void setProtocolMappers(Set<String> protocolMappers) {
this.protocolMappers = protocolMappers;
}
public Set<String> getRoles() {
return roles;
}
public void setRoles(Set<String> roles) {
this.roles = roles;
}
public Map<String, String> getNotes() {
return notes;
}
@ -348,5 +308,21 @@ public class PersistentAuthenticatedClientSessionAdapter implements Authenticate
public void setRequiredActions(Set<String> requiredActions) {
this.requiredActions = requiredActions;
}
public Set<String> getProtocolMappers() {
return protocolMappers;
}
public void setProtocolMappers(Set<String> protocolMappers) {
this.protocolMappers = protocolMappers;
}
public Set<String> getRoles() {
return roles;
}
public void setRoles(Set<String> roles) {
this.roles = roles;
}
}
}

View file

@ -40,7 +40,6 @@ public class PersistentUserSessionAdapter implements OfflineUserSessionModel {
private final PersistentUserSessionModel model;
private UserModel user;
private String userId;
private String username;
private final RealmModel realm;
private KeycloakSession session;
private final Map<String, AuthenticatedClientSessionModel> authenticatedClientSessions;

View file

@ -0,0 +1,64 @@
/*
* Copyright 2017 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.models.utils;
import java.util.List;
import org.keycloak.OAuth2Constants;
import org.keycloak.models.ClientScopeModel;
import org.keycloak.models.Constants;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.protocol.LoginProtocol;
import org.keycloak.protocol.LoginProtocolFactory;
import org.keycloak.provider.ProviderFactory;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class DefaultClientScopes {
/**
*
* @param session
* @param realm
* @param addScopesToExistingClients true when creating new realm. False when migrating from previous version
*/
public static void createDefaultClientScopes(KeycloakSession session, RealmModel realm, boolean addScopesToExistingClients) {
List<ProviderFactory> loginProtocolFactories = session.getKeycloakSessionFactory().getProviderFactories(LoginProtocol.class);
for (ProviderFactory factory : loginProtocolFactories) {
LoginProtocolFactory lpf = (LoginProtocolFactory) factory;
lpf.createDefaultClientScopes(realm, addScopesToExistingClients);
}
}
// Asumption is that newRealm and offlineRole are not null AND offline_access clientScope doesn't yet exists in the realm. Caller of this method is supposed to ensure that.
public static void createOfflineAccessClientScope(RealmModel newRealm, RoleModel offlineRole) {
ClientScopeModel offlineAccessScope = newRealm.addClientScope(OAuth2Constants.OFFLINE_ACCESS);
offlineAccessScope.setDescription("OpenID Connect built-in scope: offline_access");
offlineAccessScope.setDisplayOnConsentScreen(true);
offlineAccessScope.setConsentScreenText(Constants.OFFLINE_ACCESS_SCOPE_CONSENT_TEXT);
offlineAccessScope.setProtocol("openid-connect");
offlineAccessScope.addScopeMapping(offlineRole);
// Optional scope. Needs to be requested by scope parameter
newRealm.addDefaultClientScope(offlineAccessScope, false);
}
}

View file

@ -26,7 +26,7 @@ import org.keycloak.component.ComponentModel;
import org.keycloak.models.AuthenticationExecutionModel;
import org.keycloak.models.AuthenticationFlowModel;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientTemplateModel;
import org.keycloak.models.ClientScopeModel;
import org.keycloak.models.Constants;
import org.keycloak.models.GroupModel;
import org.keycloak.models.IdentityProviderModel;
@ -303,13 +303,16 @@ public final class KeycloakModelUtils {
return str==null ? null : str.toLowerCase();
}
public static void setupOfflineTokens(RealmModel realm) {
if (realm.getRole(Constants.OFFLINE_ACCESS_ROLE) == null) {
RoleModel role = realm.addRole(Constants.OFFLINE_ACCESS_ROLE);
role.setDescription("${role_offline-access}");
role.setScopeParamRequired(true);
public static RoleModel setupOfflineRole(RealmModel realm) {
RoleModel offlineRole = realm.getRole(Constants.OFFLINE_ACCESS_ROLE);
if (offlineRole == null) {
offlineRole = realm.addRole(Constants.OFFLINE_ACCESS_ROLE);
offlineRole.setDescription("${role_offline-access}");
realm.addDefaultRole(Constants.OFFLINE_ACCESS_ROLE);
}
return offlineRole;
}
@ -500,29 +503,54 @@ public final class KeycloakModelUtils {
}
public static boolean isClientTemplateUsed(RealmModel realm, ClientTemplateModel template) {
public static boolean isClientScopeUsed(RealmModel realm, ClientScopeModel clientScope) {
for (ClientModel client : realm.getClients()) {
if (client.getClientTemplate() != null && client.getClientTemplate().getId().equals(template.getId())) return true;
if ((client.getClientScopes(true, false).containsKey(clientScope.getName())) ||
(client.getClientScopes(false, false).containsKey(clientScope.getName()))) {
return true;
}
}
return false;
}
public static ClientTemplateModel getClientTemplateByName(RealmModel realm, String templateName) {
for (ClientTemplateModel clientTemplate : realm.getClientTemplates()) {
if (templateName.equals(clientTemplate.getName())) {
return clientTemplate;
public static ClientScopeModel getClientScopeByName(RealmModel realm, String clientScopeName) {
for (ClientScopeModel clientScope : realm.getClientScopes()) {
if (clientScopeName.equals(clientScope.getName())) {
return clientScope;
}
}
return null;
}
/**
* Lookup clientScope OR client by id. Method is useful if you know just ID, but you don't know
* if underlying model is clientScope or client
*/
public static ClientScopeModel findClientScopeById(RealmModel realm, String clientScopeId) {
ClientScopeModel clientScope = realm.getClientScopeById(clientScopeId);
if (clientScope != null) {
return clientScope;
} else {
return realm.getClientById(clientScopeId);
}
}
/** Replace spaces in the name with underscore, so that scope name can be used as value of scope parameter **/
public static String convertClientScopeName(String previousName) {
if (previousName.contains(" ")) {
return previousName.replaceAll(" ", "_");
} else {
return previousName;
}
}
public static void setupAuthorizationServices(RealmModel realm) {
for (String roleName : Constants.AUTHZ_DEFAULT_AUTHORIZATION_ROLES) {
if (realm.getRole(roleName) == null) {
RoleModel role = realm.addRole(roleName);
role.setDescription("${role_" + roleName + "}");
role.setScopeParamRequired(false);
realm.addDefaultRole(roleName);
}
}

View file

@ -211,7 +211,6 @@ public class ModelToRepresentation {
rep.setId(role.getId());
rep.setName(role.getName());
rep.setDescription(role.getDescription());
rep.setScopeParamRequired(role.isScopeParamRequired());
rep.setComposite(role.isComposite());
rep.setClientRole(role.isClientRole());
rep.setContainerId(role.getContainerId());
@ -468,20 +467,21 @@ public class ModelToRepresentation {
return rep;
}
public static ClientTemplateRepresentation toRepresentation(ClientTemplateModel clientModel) {
ClientTemplateRepresentation rep = new ClientTemplateRepresentation();
rep.setId(clientModel.getId());
rep.setName(clientModel.getName());
rep.setDescription(clientModel.getDescription());
rep.setProtocol(clientModel.getProtocol());
if (!clientModel.getProtocolMappers().isEmpty()) {
public static ClientScopeRepresentation toRepresentation(ClientScopeModel clientScopeModel) {
ClientScopeRepresentation rep = new ClientScopeRepresentation();
rep.setId(clientScopeModel.getId());
rep.setName(clientScopeModel.getName());
rep.setDescription(clientScopeModel.getDescription());
rep.setProtocol(clientScopeModel.getProtocol());
if (!clientScopeModel.getProtocolMappers().isEmpty()) {
List<ProtocolMapperRepresentation> mappings = new LinkedList<>();
for (ProtocolMapperModel model : clientModel.getProtocolMappers()) {
for (ProtocolMapperModel model : clientScopeModel.getProtocolMappers()) {
mappings.add(toRepresentation(model));
}
rep.setProtocolMappers(mappings);
}
rep.setFullScopeAllowed(clientModel.isFullScopeAllowed());
rep.setAttributes(new HashMap<>(clientScopeModel.getAttributes()));
return rep;
}
@ -515,7 +515,9 @@ public class ModelToRepresentation {
rep.setNotBefore(clientModel.getNotBefore());
rep.setNodeReRegistrationTimeout(clientModel.getNodeReRegistrationTimeout());
rep.setClientAuthenticatorType(clientModel.getClientAuthenticatorType());
if (clientModel.getClientTemplate() != null) rep.setClientTemplate(clientModel.getClientTemplate().getName());
rep.setDefaultClientScopes(new LinkedList<>(clientModel.getClientScopes(true, false).keySet()));
rep.setOptionalClientScopes(new LinkedList<>(clientModel.getClientScopes(false, false).keySet()));
Set<String> redirectUris = clientModel.getRedirectUris();
if (redirectUris != null) {
@ -542,9 +544,6 @@ public class ModelToRepresentation {
}
rep.setProtocolMappers(mappings);
}
rep.setUseTemplateMappers(clientModel.useTemplateMappers());
rep.setUseTemplateConfig(clientModel.useTemplateConfig());
rep.setUseTemplateScope(clientModel.useTemplateScope());
return rep;
}
@ -596,8 +595,6 @@ public class ModelToRepresentation {
rep.setConfig(config);
rep.setName(model.getName());
rep.setProtocolMapper(model.getProtocolMapper());
rep.setConsentText(model.getConsentText());
rep.setConsentRequired(model.isConsentRequired());
return rep;
}
@ -616,33 +613,14 @@ public class ModelToRepresentation {
public static UserConsentRepresentation toRepresentation(UserConsentModel model) {
String clientId = model.getClient().getClientId();
Map<String, List<String>> grantedProtocolMappers = new HashMap<String, List<String>>();
for (ProtocolMapperModel protocolMapper : model.getGrantedProtocolMappers()) {
String protocol = protocolMapper.getProtocol();
List<String> currentProtocolMappers = grantedProtocolMappers.computeIfAbsent(protocol, k -> new LinkedList<String>());
currentProtocolMappers.add(protocolMapper.getName());
List<String> grantedClientScopes = new LinkedList<>();
for (ClientScopeModel clientScope : model.getGrantedClientScopes()) {
grantedClientScopes.add(clientScope.getName());
}
List<String> grantedRealmRoles = new LinkedList<String>();
Map<String, List<String>> grantedClientRoles = new HashMap<String, List<String>>();
for (RoleModel role : model.getGrantedRoles()) {
if (role.getContainer() instanceof RealmModel) {
grantedRealmRoles.add(role.getName());
} else {
ClientModel client2 = (ClientModel) role.getContainer();
String clientId2 = client2.getClientId();
List<String> currentClientRoles = grantedClientRoles.computeIfAbsent(clientId2, k -> new LinkedList<String>());
currentClientRoles.add(role.getName());
}
}
UserConsentRepresentation consentRep = new UserConsentRepresentation();
consentRep.setClientId(clientId);
consentRep.setGrantedProtocolMappers(grantedProtocolMappers);
consentRep.setGrantedRealmRoles(grantedRealmRoles);
consentRep.setGrantedClientRoles(grantedClientRoles);
consentRep.setGrantedClientScopes(grantedClientScopes);
consentRep.setCreatedDate(model.getCreatedDate());
consentRep.setLastUpdatedDate(model.getLastUpdatedDate());
return consentRep;

View file

@ -32,6 +32,7 @@ import java.util.function.Function;
import java.util.stream.Collectors;
import org.jboss.logging.Logger;
import org.keycloak.OAuth2Constants;
import org.keycloak.authorization.AuthorizationProvider;
import org.keycloak.authorization.AuthorizationProviderFactory;
import org.keycloak.authorization.model.PermissionTicket;
@ -61,7 +62,7 @@ import org.keycloak.models.AuthenticatorConfigModel;
import org.keycloak.models.BrowserSecurityHeaders;
import org.keycloak.models.ClaimMask;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientTemplateModel;
import org.keycloak.models.ClientScopeModel;
import org.keycloak.models.Constants;
import org.keycloak.models.FederatedIdentityModel;
import org.keycloak.models.GroupModel;
@ -91,6 +92,7 @@ import org.keycloak.representations.idm.AuthenticationFlowRepresentation;
import org.keycloak.representations.idm.AuthenticatorConfigRepresentation;
import org.keycloak.representations.idm.ClaimRepresentation;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.ClientScopeRepresentation;
import org.keycloak.representations.idm.ClientTemplateRepresentation;
import org.keycloak.representations.idm.ComponentExportRepresentation;
import org.keycloak.representations.idm.ComponentRepresentation;
@ -144,6 +146,7 @@ public class RepresentationToModel {
public static void importRealm(KeycloakSession session, RealmRepresentation rep, RealmModel newRealm, boolean skipUserDependent) {
convertDeprecatedSocialProviders(rep);
convertDeprecatedApplications(session, rep);
convertDeprecatedClientTemplates(rep);
newRealm.setName(rep.getRealm());
if (rep.getDisplayName() != null) newRealm.setDisplayName(rep.getDisplayName());
@ -258,8 +261,29 @@ public class RepresentationToModel {
importIdentityProviders(rep, newRealm);
importIdentityProviderMappers(rep, newRealm);
if (rep.getClientTemplates() != null) {
createClientTemplates(session, rep, newRealm);
Map<String, ClientScopeModel> clientScopes = new HashMap<>();
if (rep.getClientScopes() != null) {
clientScopes = createClientScopes(session, rep.getClientScopes(), newRealm);
}
if (rep.getDefaultDefaultClientScopes() != null) {
for (String clientScopeName : rep.getDefaultDefaultClientScopes()) {
ClientScopeModel clientScope = clientScopes.get(clientScopeName);
if (clientScope != null) {
newRealm.addDefaultClientScope(clientScope, true);
} else {
logger.warnf("Referenced client scope '%s' doesn't exists", clientScopeName);
}
}
}
if (rep.getDefaultOptionalClientScopes() != null) {
for (String clientScopeName : rep.getDefaultOptionalClientScopes()) {
ClientScopeModel clientScope = clientScopes.get(clientScopeName);
if (clientScope != null) {
newRealm.addDefaultClientScope(clientScope, false);
} else {
logger.warnf("Referenced client scope '%s' doesn't exists", clientScopeName);
}
}
}
if (rep.getClients() != null) {
@ -471,8 +495,6 @@ public class RepresentationToModel {
// Application role may already exists (for example if it is defaultRole)
RoleModel role = roleRep.getId() != null ? client.addRole(roleRep.getId(), roleRep.getName()) : client.addRole(roleRep.getName());
role.setDescription(roleRep.getDescription());
boolean scopeParamRequired = roleRep.isScopeParamRequired() == null ? false : roleRep.isScopeParamRequired();
role.setScopeParamRequired(scopeParamRequired);
}
}
}
@ -762,6 +784,28 @@ public class RepresentationToModel {
}
}
private static void convertDeprecatedClientTemplates(RealmRepresentation realm) {
if (realm.getClientTemplates() != null) {
logger.warnf("Using deprecated 'clientTemplates' configuration in JSON representation for realm '%s'. It will be removed in future versions", realm.getRealm());
List<ClientScopeRepresentation> clientScopes = new LinkedList<>();
for (ClientTemplateRepresentation template : realm.getClientTemplates()) {
ClientScopeRepresentation scopeRep = new ClientScopeRepresentation();
scopeRep.setId(template.getId());
scopeRep.setName(template.getName());
scopeRep.setProtocol(template.getProtocol());
scopeRep.setDescription(template.getDescription());
scopeRep.setAttributes(template.getAttributes());
scopeRep.setProtocolMappers(template.getProtocolMappers());
clientScopes.add(scopeRep);
}
realm.setClientScopes(clientScopes);
}
}
public static void renameRealm(RealmModel realm, String name) {
if (name.equals(realm.getName())) return;
@ -973,8 +1017,6 @@ public class RepresentationToModel {
public static void createRole(RealmModel newRealm, RoleRepresentation roleRep) {
RoleModel role = roleRep.getId() != null ? newRealm.addRole(roleRep.getId(), roleRep.getName()) : newRealm.addRole(roleRep.getName());
if (roleRep.getDescription() != null) role.setDescription(roleRep.getDescription());
boolean scopeParamRequired = roleRep.isScopeParamRequired() == null ? false : roleRep.isScopeParamRequired();
role.setScopeParamRequired(scopeParamRequired);
}
private static void addComposites(RoleModel role, RoleRepresentation roleRep, RealmModel realm) {
@ -1159,40 +1201,51 @@ public class RepresentationToModel {
}
if (resourceRep.getClientTemplate() != null) {
for (ClientTemplateModel template : realm.getClientTemplates()) {
if (template.getName().equals(resourceRep.getClientTemplate())) {
client.setClientTemplate(template);
break;
}
MigrationUtils.updateProtocolMappers(template);
String clientTemplateName = KeycloakModelUtils.convertClientScopeName(resourceRep.getClientTemplate());
addClientScopeToClient(realm, client, clientTemplateName, true);
}
if (resourceRep.getDefaultClientScopes() != null) {
// First remove all default/built in client scopes
for (ClientScopeModel clientScope : client.getClientScopes(true, false).values()) {
client.removeClientScope(clientScope);
}
for (String clientScopeName : resourceRep.getDefaultClientScopes()) {
addClientScopeToClient(realm, client, clientScopeName, true);
}
}
if (resourceRep.getOptionalClientScopes() != null) {
// First remove all default/built in client scopes
for (ClientScopeModel clientScope : client.getClientScopes(false, false).values()) {
client.removeClientScope(clientScope);
}
for (String clientScopeName : resourceRep.getOptionalClientScopes()) {
addClientScopeToClient(realm, client, clientScopeName, false);
}
}
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());
}
client.setFullScopeAllowed(!client.isConsentRequired());
}
if (resourceRep.isUseTemplateConfig() != null) client.setUseTemplateConfig(resourceRep.isUseTemplateConfig());
else client.setUseTemplateConfig(false); // default to false for now
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);
client.updateClient();
return client;
}
private static void addClientScopeToClient(RealmModel realm, ClientModel client, String clientScopeName, boolean defaultScope) {
ClientScopeModel clientScope = KeycloakModelUtils.getClientScopeByName(realm, clientScopeName);
if (clientScope != null) {
client.addClientScope(clientScope, defaultScope);
} else {
logger.warnf("Referenced client scope '%s' doesn't exists. Ignoring", clientScopeName);
}
}
public static void updateClient(ClientRepresentation rep, ClientModel resource) {
if (rep.getClientId() != null) resource.setClientId(rep.getClientId());
if (rep.getName() != null) resource.setName(rep.getName());
@ -1267,108 +1320,57 @@ 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.getSecret() != null) resource.setSecret(rep.getSecret());
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;
}
}
}
}
resource.updateClient();
}
// CLIENT TEMPLATES
// CLIENT SCOPES
private static Map<String, ClientTemplateModel> createClientTemplates(KeycloakSession session, RealmRepresentation rep, RealmModel realm) {
Map<String, ClientTemplateModel> appMap = new HashMap<>();
for (ClientTemplateRepresentation resourceRep : rep.getClientTemplates()) {
ClientTemplateModel app = createClientTemplate(session, realm, resourceRep);
private static Map<String, ClientScopeModel> createClientScopes(KeycloakSession session, List<ClientScopeRepresentation> clientScopes, RealmModel realm) {
Map<String, ClientScopeModel> appMap = new HashMap<>();
for (ClientScopeRepresentation resourceRep : clientScopes) {
ClientScopeModel app = createClientScope(session, realm, resourceRep);
appMap.put(app.getName(), app);
}
return appMap;
}
public static ClientTemplateModel createClientTemplate(KeycloakSession session, RealmModel realm, ClientTemplateRepresentation resourceRep) {
logger.debug("Create client template: {0}" + resourceRep.getName());
public static ClientScopeModel createClientScope(KeycloakSession session, RealmModel realm, ClientScopeRepresentation resourceRep) {
logger.debug("Create client scope: {0}" + resourceRep.getName());
ClientTemplateModel client = resourceRep.getId() != null ? realm.addClientTemplate(resourceRep.getId(), resourceRep.getName()) : realm.addClientTemplate(resourceRep.getName());
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());
ClientScopeModel clientScope = resourceRep.getId() != null ? realm.addClientScope(resourceRep.getId(), resourceRep.getName()) : realm.addClientScope(resourceRep.getName());
if (resourceRep.getName() != null) clientScope.setName(resourceRep.getName());
if (resourceRep.getDescription() != null) clientScope.setDescription(resourceRep.getDescription());
if (resourceRep.getProtocol() != null) clientScope.setProtocol(resourceRep.getProtocol());
if (resourceRep.getProtocolMappers() != null) {
// first, remove all default/built in mappers
Set<ProtocolMapperModel> mappers = client.getProtocolMappers();
for (ProtocolMapperModel mapper : mappers) client.removeProtocolMapper(mapper);
Set<ProtocolMapperModel> mappers = clientScope.getProtocolMappers();
for (ProtocolMapperModel mapper : mappers) clientScope.removeProtocolMapper(mapper);
for (ProtocolMapperRepresentation mapper : resourceRep.getProtocolMappers()) {
client.addProtocolMapper(toModel(mapper));
clientScope.addProtocolMapper(toModel(mapper));
}
MigrationUtils.updateProtocolMappers(clientScope);
}
if (resourceRep.isBearerOnly() != null) client.setBearerOnly(resourceRep.isBearerOnly());
if (resourceRep.isConsentRequired() != null) client.setConsentRequired(resourceRep.isConsentRequired());
if (resourceRep.isStandardFlowEnabled() != null)
client.setStandardFlowEnabled(resourceRep.isStandardFlowEnabled());
if (resourceRep.isImplicitFlowEnabled() != null)
client.setImplicitFlowEnabled(resourceRep.isImplicitFlowEnabled());
if (resourceRep.isDirectAccessGrantsEnabled() != null)
client.setDirectAccessGrantsEnabled(resourceRep.isDirectAccessGrantsEnabled());
if (resourceRep.isServiceAccountsEnabled() != null)
client.setServiceAccountsEnabled(resourceRep.isServiceAccountsEnabled());
if (resourceRep.isPublicClient() != null) client.setPublicClient(resourceRep.isPublicClient());
if (resourceRep.isFrontchannelLogout() != null)
client.setFrontchannelLogout(resourceRep.isFrontchannelLogout());
if (resourceRep.getAttributes() != null) {
for (Map.Entry<String, String> entry : resourceRep.getAttributes().entrySet()) {
client.setAttribute(entry.getKey(), entry.getValue());
clientScope.setAttribute(entry.getKey(), entry.getValue());
}
}
return client;
return clientScope;
}
public static void updateClientTemplate(ClientTemplateRepresentation rep, ClientTemplateModel resource) {
public static void updateClientScope(ClientScopeRepresentation rep, ClientScopeModel 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());
if (rep.isBearerOnly() != null) resource.setBearerOnly(rep.isBearerOnly());
if (rep.isConsentRequired() != null) resource.setConsentRequired(rep.isConsentRequired());
if (rep.isStandardFlowEnabled() != null) resource.setStandardFlowEnabled(rep.isStandardFlowEnabled());
if (rep.isImplicitFlowEnabled() != null) resource.setImplicitFlowEnabled(rep.isImplicitFlowEnabled());
if (rep.isDirectAccessGrantsEnabled() != null)
resource.setDirectAccessGrantsEnabled(rep.isDirectAccessGrantsEnabled());
if (rep.isServiceAccountsEnabled() != null) resource.setServiceAccountsEnabled(rep.isServiceAccountsEnabled());
if (rep.isPublicClient() != null) resource.setPublicClient(rep.isPublicClient());
if (rep.isFullScopeAllowed() != null) resource.setFullScopeAllowed(rep.isFullScopeAllowed());
if (rep.isFrontchannelLogout() != null) resource.setFrontchannelLogout(rep.isFrontchannelLogout());
if (rep.getAttributes() != null) {
for (Map.Entry<String, String> entry : rep.getAttributes().entrySet()) {
resource.setAttribute(entry.getKey(), entry.getValue());
@ -1456,14 +1458,21 @@ public class RepresentationToModel {
throw new RuntimeException("Unknown client specification in scope mappings: " + scope.getClient());
}
return client;
} else if (scope.getClientTemplate() != null) {
ClientTemplateModel clientTemplate = KeycloakModelUtils.getClientTemplateByName(realm, scope.getClientTemplate());
} else if (scope.getClientScope() != null) {
ClientScopeModel clientScope = KeycloakModelUtils.getClientScopeByName(realm, scope.getClientScope());
if (clientScope == null) {
throw new RuntimeException("Unknown clientScope specification in scope mappings: " + scope.getClientScope());
}
return clientScope;
} else if (scope.getClientTemplate() != null) { // Backwards compatibility
String templateName = KeycloakModelUtils.convertClientScopeName(scope.getClientTemplate());
ClientScopeModel clientTemplate = KeycloakModelUtils.getClientScopeByName(realm, templateName);
if (clientTemplate == null) {
throw new RuntimeException("Unknown clientTemplate specification in scope mappings: " + scope.getClientTemplate());
throw new RuntimeException("Unknown clientScope specification in scope mappings: " + templateName);
}
return clientTemplate;
} else {
throw new RuntimeException("Either client or clientTemplate needs to be specified in scope mappings");
throw new RuntimeException("Either client or clientScope needs to be specified in scope mappings");
}
}
@ -1734,8 +1743,6 @@ public class RepresentationToModel {
ProtocolMapperModel model = new ProtocolMapperModel();
model.setId(rep.getId());
model.setName(rep.getName());
model.setConsentRequired(rep.isConsentRequired());
model.setConsentText(rep.getConsentText());
model.setProtocol(rep.getProtocol());
model.setProtocolMapper(rep.getProtocolMapper());
model.setConfig(removeEmptyString(rep.getConfig()));
@ -1762,44 +1769,27 @@ public class RepresentationToModel {
consentModel.setCreatedDate(consentRep.getCreatedDate());
consentModel.setLastUpdatedDate(consentRep.getLastUpdatedDate());
if (consentRep.getGrantedRealmRoles() != null) {
for (String roleName : consentRep.getGrantedRealmRoles()) {
RoleModel role = newRealm.getRole(roleName);
if (role == null) {
throw new RuntimeException("Unable to find realm role referenced in consent mappings of user. Role name: " + roleName);
if (consentRep.getGrantedClientScopes() != null) {
for (String scopeName : consentRep.getGrantedClientScopes()) {
ClientScopeModel clientScope = KeycloakModelUtils.getClientScopeByName(newRealm, scopeName);
if (clientScope == null) {
throw new RuntimeException("Unable to find client scope referenced in consent mappings of user. Client scope name: " + scopeName);
}
consentModel.addGrantedRole(role);
consentModel.addGrantedClientScope(clientScope);
}
}
if (consentRep.getGrantedClientRoles() != null) {
for (Map.Entry<String, List<String>> entry : consentRep.getGrantedClientRoles().entrySet()) {
String clientId2 = entry.getKey();
ClientModel client2 = newRealm.getClientByClientId(clientId2);
if (client2 == null) {
throw new RuntimeException("Unable to find client referenced in consent mappings. Client ID: " + clientId2);
}
for (String clientRoleName : entry.getValue()) {
RoleModel clientRole = client2.getRole(clientRoleName);
if (clientRole == null) {
throw new RuntimeException("Unable to find client role referenced in consent mappings of user. Role name: " + clientRole + ", Client: " + clientId2);
}
consentModel.addGrantedRole(clientRole);
}
}
}
if (consentRep.getGrantedProtocolMappers() != null) {
for (Map.Entry<String, List<String>> protocolEntry : consentRep.getGrantedProtocolMappers().entrySet()) {
String protocol = protocolEntry.getKey();
for (String protocolMapperName : protocolEntry.getValue()) {
ProtocolMapperModel protocolMapper = client.getProtocolMapperByName(protocol, protocolMapperName);
if (protocolMapper == null) {
throw new RuntimeException("Unable to find protocol mapper for protocol " + protocol + ", mapper name " + protocolMapperName);
}
consentModel.addGrantedProtocolMapper(protocolMapper);
// Backwards compatibility. If user had consent for "offline_access" role, we treat it as he has consent for "offline_access" client scope
if (consentRep.getGrantedRealmRoles() != null) {
if (consentRep.getGrantedRealmRoles().contains(OAuth2Constants.OFFLINE_ACCESS)) {
ClientScopeModel offlineScope = client.getClientScopes(false, true).get(OAuth2Constants.OFFLINE_ACCESS);
if (offlineScope == null) {
logger.warn("Unable to find offline_access scope referenced in grantedRoles of user");
}
consentModel.addGrantedClientScope(offlineScope);
}
}
return consentModel;
}

View file

@ -19,6 +19,7 @@ package org.keycloak.protocol;
import org.keycloak.Config;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientScopeModel;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.RealmModel;
import org.keycloak.provider.ProviderEvent;
@ -41,12 +42,45 @@ public abstract class AbstractLoginProtocolFactory implements LoginProtocolFacto
public void onEvent(ProviderEvent event) {
if (event instanceof RealmModel.ClientCreationEvent) {
ClientModel client = ((RealmModel.ClientCreationEvent)event).getCreatedClient();
addDefaultClientScopes(client.getRealm(), client);
addDefaults(client);
}
}
});
}
@Override
public void createDefaultClientScopes(RealmModel newRealm, boolean addScopesToExistingClients) {
createDefaultClientScopesImpl(newRealm);
// Create default client scopes for realm built-in clients too
if (addScopesToExistingClients) {
for (ClientModel client : newRealm.getClients()) {
addDefaultClientScopes(newRealm, client);
}
}
}
/**
* Impl should create default client scopes. This is called usually when new realm is created
*/
protected abstract void createDefaultClientScopesImpl(RealmModel newRealm);
protected void addDefaultClientScopes(RealmModel realm, ClientModel newClient) {
for (ClientScopeModel clientScope : realm.getDefaultClientScopes(true)) {
if (getId().equals(clientScope.getProtocol())) {
newClient.addClientScope(clientScope, true);
}
}
for (ClientScopeModel clientScope : realm.getDefaultClientScopes(false)) {
if (getId().equals(clientScope.getProtocol())) {
newClient.addClientScope(clientScope, false);
}
}
}
protected abstract void addDefaults(ClientModel realm);
@Override

View file

@ -20,6 +20,7 @@ package org.keycloak.protocol;
import org.keycloak.events.EventBuilder;
import org.keycloak.models.AuthenticatedClientSessionModel;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientSessionContext;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserSessionModel;
@ -67,7 +68,7 @@ public interface LoginProtocol extends Provider {
LoginProtocol setEventBuilder(EventBuilder event);
Response authenticated(UserSessionModel userSession, AuthenticatedClientSessionModel clientSession);
Response authenticated(UserSessionModel userSession, ClientSessionContext clientSessionCtx);
Response sendError(AuthenticationSessionModel authSession, Error error);

View file

@ -19,14 +19,11 @@ package org.keycloak.protocol;
import org.keycloak.events.EventBuilder;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientTemplateModel;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.RealmModel;
import org.keycloak.provider.ProviderFactory;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.ClientTemplateRepresentation;
import java.util.List;
import java.util.Map;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@ -38,16 +35,21 @@ public interface LoginProtocolFactory extends ProviderFactory<LoginProtocol> {
*
* @return
*/
List<ProtocolMapperModel> getBuiltinMappers();
Map<String, ProtocolMapperModel> getBuiltinMappers();
/**
* List of mappers, which are added to new clients by default
* @return
*/
List<ProtocolMapperModel> getDefaultBuiltinMappers();
Object createProtocolEndpoint(RealmModel realm, EventBuilder event);
/**
* Called when new realm is created
*
* @param newRealm
* @param addScopesToExistingClients If true, then existing realm clients will be updated (created realm default scopes will be added to them)
*/
void createDefaultClientScopes(RealmModel newRealm, boolean addScopesToExistingClients);
/**
* Setup default values for new clients. This expects that the representation has already set up the client
*
@ -56,11 +58,4 @@ public interface LoginProtocolFactory extends ProviderFactory<LoginProtocol> {
*/
void setupClientDefaults(ClientRepresentation rep, ClientModel newClient);
/**
* Setup default values for new templates. This expects that the representation has already set up the template
*
* @param clientRep
* @param newClient
*/
void setupTemplateDefaults(ClientTemplateRepresentation clientRep, ClientTemplateModel newClient);
}

View file

@ -16,7 +16,7 @@
*/
package org.keycloak.storage.client;
import org.keycloak.models.ClientTemplateModel;
import org.keycloak.models.ClientScopeModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.RealmModel;
@ -214,27 +214,13 @@ public abstract class AbstractReadOnlyClientStorageAdapter extends AbstractClien
}
@Override
public void setClientTemplate(ClientTemplateModel template) {
throw new ReadOnlyException("client is read only for this update");
}
@Override
public void setUseTemplateScope(boolean flag) {
public void addClientScope(ClientScopeModel clientScope, boolean defaultScope) {
throw new ReadOnlyException("client is read only for this update");
}
@Override
public void setUseTemplateMappers(boolean flag) {
public void removeClientScope(ClientScopeModel clientScope) {
throw new ReadOnlyException("client is read only for this update");
}
@Override
public void setUseTemplateConfig(boolean flag) {
throw new ReadOnlyException("client is read only for this update");
}
@Override

View file

@ -24,7 +24,7 @@ import java.util.Set;
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public interface ClientModel extends RoleContainerModel, ProtocolMapperContainerModel, ScopeContainerModel {
public interface ClientModel extends ClientScopeModel, RoleContainerModel, ProtocolMapperContainerModel, ScopeContainerModel {
// COMMON ATTRIBUTES
@ -133,6 +133,9 @@ public interface ClientModel extends RoleContainerModel, ProtocolMapperContaine
boolean isFrontchannelLogout();
void setFrontchannelLogout(boolean flag);
boolean isFullScopeAllowed();
void setFullScopeAllowed(boolean value);
boolean isPublicClient();
void setPublicClient(boolean flag);
@ -154,14 +157,24 @@ public interface ClientModel extends RoleContainerModel, ProtocolMapperContaine
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);
/**
* Add clientScope with this client. Add it as default scope (if parameter 'defaultScope' is true) or optional scope (if parameter 'defaultScope' is false)
* @param clientScope
* @param defaultScope
*/
void addClientScope(ClientScopeModel clientScope, boolean defaultScope);
void removeClientScope(ClientScopeModel clientScope);
/**
* Return all default scopes (if 'defaultScope' is true) or all optional scopes (if 'defaultScope' is false) linked with this client
*
* @param defaultScope
* @param filterByProtocol if true, then just client scopes of same protocol like current client will be returned
* @return map where key is the name of the clientScope, value is particular clientScope. Returns empty map if no scopes linked (never returns null).
*/
Map<String, ClientScopeModel> getClientScopes(boolean defaultScope, boolean filterByProtocol);
/**
* Time in seconds since epoc
@ -183,4 +196,22 @@ public interface ClientModel extends RoleContainerModel, ProtocolMapperContaine
void registerNode(String nodeHost, int registrationTime);
void unregisterNode(String nodeHost);
// Clients are not displayed on consent screen by default
@Override
default boolean isDisplayOnConsentScreen() {
String displayVal = getAttribute(DISPLAY_ON_CONSENT_SCREEN);
return displayVal==null ? false : Boolean.parseBoolean(displayVal);
}
// Fallback to name or clientId if consentScreenText attribute is null
@Override
default String getConsentScreenText() {
String consentScreenText = ClientScopeModel.super.getConsentScreenText();
if (consentScreenText == null) {
consentScreenText = getClientId();
}
return consentScreenText;
}
}

View file

@ -23,7 +23,7 @@ import java.util.Map;
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public interface ClientTemplateModel extends ProtocolMapperContainerModel, ScopeContainerModel {
public interface ClientScopeModel extends ProtocolMapperContainerModel, ScopeContainerModel {
String getId();
String getName();
@ -43,30 +43,33 @@ public interface ClientTemplateModel extends ProtocolMapperContainerModel, Scope
String getAttribute(String name);
Map<String, String> getAttributes();
boolean isFrontchannelLogout();
void setFrontchannelLogout(boolean flag);
boolean isBearerOnly();
void setBearerOnly(boolean only);
// CONFIGS
boolean isPublicClient();
void setPublicClient(boolean flag);
String DISPLAY_ON_CONSENT_SCREEN = "display.on.consent.screen";
String CONSENT_SCREEN_TEXT = "consent.screen.text";
boolean isConsentRequired();
void setConsentRequired(boolean consentRequired);
default boolean isDisplayOnConsentScreen() {
String displayVal = getAttribute(DISPLAY_ON_CONSENT_SCREEN);
return displayVal==null ? true : Boolean.parseBoolean(displayVal);
}
boolean isStandardFlowEnabled();
void setStandardFlowEnabled(boolean standardFlowEnabled);
default void setDisplayOnConsentScreen(boolean displayOnConsentScreen) {
setAttribute(DISPLAY_ON_CONSENT_SCREEN, String.valueOf(displayOnConsentScreen));
}
boolean isImplicitFlowEnabled();
void setImplicitFlowEnabled(boolean implicitFlowEnabled);
boolean isDirectAccessGrantsEnabled();
void setDirectAccessGrantsEnabled(boolean directAccessGrantsEnabled);
boolean isServiceAccountsEnabled();
void setServiceAccountsEnabled(boolean serviceAccountsEnabled);
// Fallback to name if consentScreenText attribute is null
default String getConsentScreenText() {
String consentScreenText = getAttribute(CONSENT_SCREEN_TEXT);
if (consentScreenText == null) {
consentScreenText = getName();
}
return consentScreenText;
}
default void setConsentScreenText(String consentScreenText) {
setAttribute(CONSENT_SCREEN_TEXT, consentScreenText);
}
}

View file

@ -0,0 +1,40 @@
/*
* Copyright 2017 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.models;
import java.util.Set;
/**
* Request-scoped context object
*
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public interface ClientSessionContext {
AuthenticatedClientSessionModel getClientSession();
Set<String> getClientScopeIds();
Set<ClientScopeModel> getClientScopes();
Set<RoleModel> getRoles();
Set<ProtocolMapperModel> getProtocolMappers();
String getScopeString();
}

View file

@ -69,22 +69,6 @@ public class ProtocolMapperModel implements Serializable {
this.protocolMapper = protocolMapper;
}
public boolean isConsentRequired() {
return consentRequired;
}
public void setConsentRequired(boolean consentRequired) {
this.consentRequired = consentRequired;
}
public String getConsentText() {
return consentText;
}
public void setConsentText(String consentText) {
this.consentText = consentText;
}
public Map<String, String> getConfig() {
return config;
}

View file

@ -437,14 +437,18 @@ public interface RealmModel extends RoleContainerModel {
boolean removeGroup(GroupModel group);
void moveGroup(GroupModel group, GroupModel toParent);
List<ClientTemplateModel> getClientTemplates();
List<ClientScopeModel> getClientScopes();
ClientTemplateModel addClientTemplate(String name);
ClientScopeModel addClientScope(String name);
ClientTemplateModel addClientTemplate(String id, String name);
ClientScopeModel addClientScope(String id, String name);
boolean removeClientTemplate(String id);
boolean removeClientScope(String id);
ClientTemplateModel getClientTemplateById(String id);
ClientScopeModel getClientScopeById(String id);
void addDefaultClientScope(ClientScopeModel clientScope, boolean defaultScope);
void removeDefaultClientScope(ClientScopeModel clientScope);
List<ClientScopeModel> getDefaultClientScopes(boolean defaultScope);
}

View file

@ -19,7 +19,6 @@ package org.keycloak.models;
import org.keycloak.migration.MigrationModel;
import org.keycloak.provider.Provider;
import org.keycloak.storage.client.ClientLookupProvider;
import java.util.List;
import java.util.Set;
@ -72,7 +71,7 @@ public interface RealmProvider extends Provider, ClientProvider {
RoleModel getRoleById(String id, RealmModel realm);
ClientTemplateModel getClientTemplateById(String id, RealmModel realm);
ClientScopeModel getClientScopeById(String id, RealmModel realm);
GroupModel getGroupById(String id, RealmModel realm);

View file

@ -34,10 +34,6 @@ public interface RoleModel {
void setName(String name);
boolean isScopeParamRequired();
void setScopeParamRequired(boolean scopeParamRequired);
boolean isComposite();
void addCompositeRole(RoleModel role);

View file

@ -24,9 +24,6 @@ import java.util.Set;
* @version $Revision: 1 $
*/
public interface ScopeContainerModel {
boolean isFullScopeAllowed();
void setFullScopeAllowed(boolean value);
Set<RoleModel> getScopeMappings();

Some files were not shown because too many files have changed in this diff Show more