diff --git a/broker/oidc/pom.xml b/broker/oidc/pom.xml index 27fb085243..8913efb889 100755 --- a/broker/oidc/pom.xml +++ b/broker/oidc/pom.xml @@ -52,6 +52,11 @@ jboss-logging provided + + junit + junit + test + diff --git a/broker/oidc/src/main/java/org/keycloak/broker/oidc/AbstractOAuth2IdentityProvider.java b/broker/oidc/src/main/java/org/keycloak/broker/oidc/AbstractOAuth2IdentityProvider.java index 0eab543b20..0581eb10bf 100755 --- a/broker/oidc/src/main/java/org/keycloak/broker/oidc/AbstractOAuth2IdentityProvider.java +++ b/broker/oidc/src/main/java/org/keycloak/broker/oidc/AbstractOAuth2IdentityProvider.java @@ -112,11 +112,22 @@ public abstract class AbstractOAuth2IdentityProvider notes = new HashMap<>(); + tested.getFederatedIdentity("{\"cosi\":\"sss\"}"); + } + + @Test(expected = IdentityBrokerException.class) + public void getFederatedIdentity_responseJSON_invalidFormat() { + TestProvider tested = getTested(); + Map notes = new HashMap<>(); + tested.getFederatedIdentity("{\"cosi\":\"sss\""); + } + + @Test(expected = IdentityBrokerException.class) + public void getFederatedIdentity_responseJSON_emptyTokenField() { + TestProvider tested = getTested(); + tested.getFederatedIdentity("{\"" + + AbstractOAuth2IdentityProvider.OAUTH2_PARAMETER_ACCESS_TOKEN + "\" : \"\"}"); + } + + @Test(expected = IdentityBrokerException.class) + public void getFederatedIdentity_responseJSON_nullTokenField() { + TestProvider tested = getTested(); + tested.getFederatedIdentity("{\"" + + AbstractOAuth2IdentityProvider.OAUTH2_PARAMETER_ACCESS_TOKEN + "\" : null}"); + } + + @Test + public void getFederatedIdentity_responseJSON() { + TestProvider tested = getTested(); + BrokeredIdentityContext fi = tested.getFederatedIdentity("{\"" + + AbstractOAuth2IdentityProvider.OAUTH2_PARAMETER_ACCESS_TOKEN + "\" : \"458rt\"}"); + Assert.assertNotNull(fi); + Assert.assertEquals("458rt", fi.getId()); + } + + @Test + public void getFederatedIdentity_responseUrlLine() { + TestProvider tested = getTested(); + BrokeredIdentityContext fi = tested.getFederatedIdentity("cosi=sss&" + + AbstractOAuth2IdentityProvider.OAUTH2_PARAMETER_ACCESS_TOKEN + "=458rtf&kdesi=ss}"); + Assert.assertNotNull(fi); + Assert.assertEquals("458rtf", fi.getId()); + } + + private TestProvider getTested() { + IdentityProviderModel model = new IdentityProviderModel(); + OAuth2IdentityProviderConfig config = new OAuth2IdentityProviderConfig(model); + return new TestProvider(config); + } + + private static class TestProvider extends AbstractOAuth2IdentityProvider { + + public TestProvider(OAuth2IdentityProviderConfig config) { + super(config); + } + + @Override + protected String getDefaultScopes() { + return "default"; + } + + protected BrokeredIdentityContext doGetFederatedIdentity(String accessToken) { + return new BrokeredIdentityContext(accessToken); + }; + + }; + +} diff --git a/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.2.0.RC1.xml b/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.2.0.RC1.xml index 7c506009c5..6fc69db19e 100755 --- a/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.2.0.RC1.xml +++ b/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.2.0.RC1.xml @@ -36,5 +36,17 @@ + + + + + + + + + DTYPE = 'OAuthClientEntity' + + + diff --git a/connections/jpa/src/main/resources/META-INF/persistence.xml b/connections/jpa/src/main/resources/META-INF/persistence.xml index aca54ef9c2..2a066d028d 100755 --- a/connections/jpa/src/main/resources/META-INF/persistence.xml +++ b/connections/jpa/src/main/resources/META-INF/persistence.xml @@ -3,9 +3,8 @@ xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0"> - org.keycloak.models.jpa.entities.ApplicationEntity + org.keycloak.models.jpa.entities.ClientEntity org.keycloak.models.jpa.entities.CredentialEntity - org.keycloak.models.jpa.entities.OAuthClientEntity org.keycloak.models.jpa.entities.RealmEntity org.keycloak.models.jpa.entities.RealmAttributeEntity org.keycloak.models.jpa.entities.RequiredCredentialEntity diff --git a/connections/mongo-update/src/main/java/org/keycloak/connections/mongo/updater/impl/DefaultMongoUpdaterProvider.java b/connections/mongo-update/src/main/java/org/keycloak/connections/mongo/updater/impl/DefaultMongoUpdaterProvider.java index da1d2c02c8..10a13683da 100644 --- a/connections/mongo-update/src/main/java/org/keycloak/connections/mongo/updater/impl/DefaultMongoUpdaterProvider.java +++ b/connections/mongo-update/src/main/java/org/keycloak/connections/mongo/updater/impl/DefaultMongoUpdaterProvider.java @@ -10,6 +10,7 @@ import org.keycloak.connections.mongo.updater.impl.updates.Update; import org.keycloak.connections.mongo.updater.impl.updates.Update1_0_0_Final; import org.keycloak.connections.mongo.updater.impl.updates.Update1_1_0_Beta1; import org.keycloak.connections.mongo.updater.impl.updates.Update1_2_0_Beta1; +import org.keycloak.connections.mongo.updater.impl.updates.Update1_2_0_RC1; import org.keycloak.models.KeycloakSession; import java.util.Date; @@ -28,7 +29,8 @@ public class DefaultMongoUpdaterProvider implements MongoUpdaterProvider { private Class[] updates = new Class[]{ Update1_0_0_Final.class, Update1_1_0_Beta1.class, - Update1_2_0_Beta1.class + Update1_2_0_Beta1.class, + Update1_2_0_RC1.class }; @Override diff --git a/connections/mongo-update/src/main/java/org/keycloak/connections/mongo/updater/impl/updates/Update.java b/connections/mongo-update/src/main/java/org/keycloak/connections/mongo/updater/impl/updates/Update.java index 54e4b706ef..f05e79cc95 100644 --- a/connections/mongo-update/src/main/java/org/keycloak/connections/mongo/updater/impl/updates/Update.java +++ b/connections/mongo-update/src/main/java/org/keycloak/connections/mongo/updater/impl/updates/Update.java @@ -53,15 +53,8 @@ public abstract class Update { log.debugv("Deleted entries from {0}", collection); } - protected String insertApplicationRole(DBCollection roles, String roleName, String applicationId) { - BasicDBObject role = new BasicDBObject(); - String roleId = KeycloakModelUtils.generateId(); - role.append("_id", roleId); - role.append("name", roleName); - role.append("applicationId", applicationId); - role.append("nameIndex", applicationId + "//" + roleName); - roles.insert(role); - return roleId; + protected void renameCollection(String collection, String newName) { + db.getCollection(collection).rename(newName); } public void setLog(Logger log) { diff --git a/connections/mongo-update/src/main/java/org/keycloak/connections/mongo/updater/impl/updates/Update1_2_0_Beta1.java b/connections/mongo-update/src/main/java/org/keycloak/connections/mongo/updater/impl/updates/Update1_2_0_Beta1.java index 349520acb6..abaae4cd42 100644 --- a/connections/mongo-update/src/main/java/org/keycloak/connections/mongo/updater/impl/updates/Update1_2_0_Beta1.java +++ b/connections/mongo-update/src/main/java/org/keycloak/connections/mongo/updater/impl/updates/Update1_2_0_Beta1.java @@ -266,4 +266,15 @@ public class Update1_2_0_Beta1 extends Update { } } + private String insertApplicationRole(DBCollection roles, String roleName, String applicationId) { + BasicDBObject role = new BasicDBObject(); + String roleId = KeycloakModelUtils.generateId(); + role.append("_id", roleId); + role.append("name", roleName); + role.append("applicationId", applicationId); + role.append("nameIndex", applicationId + "//" + roleName); + roles.insert(role); + return roleId; + } + } diff --git a/connections/mongo-update/src/main/java/org/keycloak/connections/mongo/updater/impl/updates/Update1_2_0_RC1.java b/connections/mongo-update/src/main/java/org/keycloak/connections/mongo/updater/impl/updates/Update1_2_0_RC1.java new file mode 100644 index 0000000000..5954199e64 --- /dev/null +++ b/connections/mongo-update/src/main/java/org/keycloak/connections/mongo/updater/impl/updates/Update1_2_0_RC1.java @@ -0,0 +1,51 @@ +package org.keycloak.connections.mongo.updater.impl.updates; + +import com.mongodb.BasicDBObject; +import com.mongodb.DBCollection; +import com.mongodb.DBCursor; +import org.keycloak.models.KeycloakSession; + +/** + * @author Marek Posolda + */ +public class Update1_2_0_RC1 extends Update { + + @Override + public String getId() { + return "1.2.0.RC1"; + } + + @Override + public void update(KeycloakSession session) { + convertApplicationsToClients(); + convertOAuthClientsToClients(); + } + + private void convertApplicationsToClients() { + DBCollection applications = db.getCollection("applications"); + applications.update(new BasicDBObject(), new BasicDBObject("$set", new BasicDBObject("consentRequired", false)), false, true); + applications.update(new BasicDBObject(), new BasicDBObject("$rename", new BasicDBObject("name", "clientId")), false, true); + renameCollection("applications", "clients"); + log.debugv("Converted applications to clients"); + + DBCollection roles = db.getCollection("roles"); + roles.update(new BasicDBObject(), new BasicDBObject("$rename", new BasicDBObject("applicationId", "clientId")), false, true); + log.debugv("Renamed roles.applicationId to roles.clientId"); + } + + private void convertOAuthClientsToClients() { + DBCollection clients = db.getCollection("clients"); + DBCollection oauthClients = db.getCollection("oauthClients"); + oauthClients.update(new BasicDBObject(), new BasicDBObject("$rename", new BasicDBObject("name", "clientId")), false, true); + oauthClients.update(new BasicDBObject(), new BasicDBObject("$set", new BasicDBObject("consentRequired", true)), false, true); + + DBCursor curs = oauthClients.find(); + while (curs.hasNext()) { + clients.insert(curs.next()); + } + + oauthClients.drop(); + log.debugv("Converted oauthClients to clients"); + } + +} diff --git a/connections/mongo/src/main/java/org/keycloak/connections/mongo/DefaultMongoConnectionFactoryProvider.java b/connections/mongo/src/main/java/org/keycloak/connections/mongo/DefaultMongoConnectionFactoryProvider.java index f5ed855c34..138955bc6c 100755 --- a/connections/mongo/src/main/java/org/keycloak/connections/mongo/DefaultMongoConnectionFactoryProvider.java +++ b/connections/mongo/src/main/java/org/keycloak/connections/mongo/DefaultMongoConnectionFactoryProvider.java @@ -33,8 +33,7 @@ public class DefaultMongoConnectionFactoryProvider implements MongoConnectionPro "org.keycloak.models.entities.RequiredCredentialEntity", "org.keycloak.models.entities.CredentialEntity", "org.keycloak.models.entities.FederatedIdentityEntity", - "org.keycloak.models.mongo.keycloak.entities.MongoApplicationEntity", - "org.keycloak.models.mongo.keycloak.entities.MongoOAuthClientEntity", + "org.keycloak.models.mongo.keycloak.entities.MongoClientEntity", "org.keycloak.models.sessions.mongo.entities.MongoUsernameLoginFailureEntity", "org.keycloak.models.sessions.mongo.entities.MongoUserSessionEntity", "org.keycloak.models.sessions.mongo.entities.MongoClientSessionEntity", diff --git a/core/src/main/java/org/keycloak/constants/AdapterConstants.java b/core/src/main/java/org/keycloak/constants/AdapterConstants.java index df302b2f1e..aa223955d3 100755 --- a/core/src/main/java/org/keycloak/constants/AdapterConstants.java +++ b/core/src/main/java/org/keycloak/constants/AdapterConstants.java @@ -19,13 +19,13 @@ public interface AdapterConstants { String AUTH_DATA_PARAM_NAME = "org.keycloak.json.adapterConfig"; // Attribute passed in codeToToken request from adapter to Keycloak and saved in ClientSession. Contains ID of HttpSession on adapter - public static final String APPLICATION_SESSION_STATE = "application_session_state"; + public static final String CLIENT_SESSION_STATE = "client_session_state"; // Attribute passed in codeToToken request from adapter to Keycloak and saved in ClientSession. Contains hostname of adapter where HttpSession is served - public static final String APPLICATION_SESSION_HOST = "application_session_host"; + public static final String CLIENT_SESSION_HOST = "client_session_host"; // Attribute passed in registerNode request for register new application cluster node once he joined cluster - public static final String APPLICATION_CLUSTER_HOST = "application_cluster_host"; + public static final String CLIENT_CLUSTER_HOST = "client_cluster_host"; // Cookie used on adapter side to store token info. Used only when tokenStore is 'COOKIE' public static final String KEYCLOAK_ADAPTER_STATE_COOKIE = "KEYCLOAK_ADAPTER_STATE"; diff --git a/core/src/main/java/org/keycloak/representations/idm/ApplicationMappingsRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/ApplicationMappingsRepresentation.java deleted file mode 100755 index 30b94d2905..0000000000 --- a/core/src/main/java/org/keycloak/representations/idm/ApplicationMappingsRepresentation.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.keycloak.representations.idm; - -import java.util.List; - -/** - * @author Bill Burke - * @version $Revision: 1 $ - */ -public class ApplicationMappingsRepresentation { - protected String applicationId; - protected String application; - - protected List mappings; - - public String getApplicationId() { - return applicationId; - } - - public void setApplicationId(String applicationId) { - this.applicationId = applicationId; - } - - public String getApplication() { - return application; - } - - public void setApplication(String application) { - this.application = application; - } - - public List getMappings() { - return mappings; - } - - public void setMappings(List mappings) { - this.mappings = mappings; - } -} diff --git a/core/src/main/java/org/keycloak/representations/idm/ApplicationRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/ApplicationRepresentation.java index e407049dfa..cc9b657083 100755 --- a/core/src/main/java/org/keycloak/representations/idm/ApplicationRepresentation.java +++ b/core/src/main/java/org/keycloak/representations/idm/ApplicationRepresentation.java @@ -1,44 +1,14 @@ package org.keycloak.representations.idm; -import java.util.List; -import java.util.Map; - /** * @author Bill Burke * @version $Revision: 1 $ */ -public class ApplicationRepresentation { - protected String id; +@Deprecated +public class ApplicationRepresentation extends ClientRepresentation { protected String name; - protected String adminUrl; - protected String baseUrl; - protected Boolean surrogateAuthRequired; - protected Boolean enabled; - protected String secret; - protected String[] defaultRoles; - protected List redirectUris; - protected List webOrigins; @Deprecated protected ClaimRepresentation claims; - protected Integer notBefore; - protected Boolean bearerOnly; - protected Boolean publicClient; - protected Boolean frontchannelLogout; - protected String protocol; - protected Map attributes; - protected Boolean fullScopeAllowed; - protected Integer nodeReRegistrationTimeout; - protected Map registeredNodes; - protected List identityProviders; - protected List protocolMappers; - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } public String getName() { return name; @@ -48,70 +18,6 @@ public class ApplicationRepresentation { this.name = name; } - public Boolean isEnabled() { - return enabled; - } - - public void setEnabled(Boolean enabled) { - this.enabled = enabled; - } - - public Boolean isSurrogateAuthRequired() { - return surrogateAuthRequired; - } - - public void setSurrogateAuthRequired(Boolean surrogateAuthRequired) { - this.surrogateAuthRequired = surrogateAuthRequired; - } - - public String getAdminUrl() { - return adminUrl; - } - - public void setAdminUrl(String adminUrl) { - this.adminUrl = adminUrl; - } - - public String getBaseUrl() { - return baseUrl; - } - - public void setBaseUrl(String baseUrl) { - this.baseUrl = baseUrl; - } - - public String getSecret() { - return secret; - } - - public void setSecret(String secret) { - this.secret = secret; - } - - public List getRedirectUris() { - return redirectUris; - } - - public void setRedirectUris(List redirectUris) { - this.redirectUris = redirectUris; - } - - public List getWebOrigins() { - return webOrigins; - } - - public void setWebOrigins(List webOrigins) { - this.webOrigins = webOrigins; - } - - public String[] getDefaultRoles() { - return defaultRoles; - } - - public void setDefaultRoles(String[] defaultRoles) { - this.defaultRoles = defaultRoles; - } - public ClaimRepresentation getClaims() { return claims; } @@ -119,92 +25,4 @@ public class ApplicationRepresentation { public void setClaims(ClaimRepresentation claims) { this.claims = claims; } - - public Integer getNotBefore() { - return notBefore; - } - - public void setNotBefore(Integer notBefore) { - this.notBefore = notBefore; - } - - public Boolean isBearerOnly() { - return bearerOnly; - } - - public void setBearerOnly(Boolean bearerOnly) { - this.bearerOnly = bearerOnly; - } - - public Boolean isPublicClient() { - return publicClient; - } - - public void setPublicClient(Boolean publicClient) { - this.publicClient = publicClient; - } - - public Boolean isFullScopeAllowed() { - return fullScopeAllowed; - } - - public void setFullScopeAllowed(Boolean fullScopeAllowed) { - this.fullScopeAllowed = fullScopeAllowed; - } - - public String getProtocol() { - return protocol; - } - - public void setProtocol(String protocol) { - this.protocol = protocol; - } - - public Map getAttributes() { - return attributes; - } - - public void setAttributes(Map attributes) { - this.attributes = attributes; - } - - public Integer getNodeReRegistrationTimeout() { - return nodeReRegistrationTimeout; - } - - public void setNodeReRegistrationTimeout(Integer nodeReRegistrationTimeout) { - this.nodeReRegistrationTimeout = nodeReRegistrationTimeout; - } - - public Map getRegisteredNodes() { - return registeredNodes; - } - - public void setRegisteredNodes(Map registeredNodes) { - this.registeredNodes = registeredNodes; - } - - public Boolean isFrontchannelLogout() { - return frontchannelLogout; - } - - public void setFrontchannelLogout(Boolean frontchannelLogout) { - this.frontchannelLogout = frontchannelLogout; - } - - public List getIdentityProviders() { - return this.identityProviders; - } - - public void setIdentityProviders(List identityProviders) { - this.identityProviders = identityProviders; - } - - public List getProtocolMappers() { - return protocolMappers; - } - - public void setProtocolMappers(List protocolMappers) { - this.protocolMappers = protocolMappers; - } } diff --git a/core/src/main/java/org/keycloak/representations/idm/ClientMappingsRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/ClientMappingsRepresentation.java new file mode 100755 index 0000000000..8f87c8ab68 --- /dev/null +++ b/core/src/main/java/org/keycloak/representations/idm/ClientMappingsRepresentation.java @@ -0,0 +1,38 @@ +package org.keycloak.representations.idm; + +import java.util.List; + +/** + * @author Bill Burke + * @version $Revision: 1 $ + */ +public class ClientMappingsRepresentation { + protected String id; + protected String client; + + protected List mappings; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getClient() { + return client; + } + + public void setClient(String client) { + this.client = client; + } + + public List getMappings() { + return mappings; + } + + public void setMappings(List mappings) { + this.mappings = mappings; + } +} diff --git a/core/src/main/java/org/keycloak/representations/idm/ClientRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/ClientRepresentation.java new file mode 100755 index 0000000000..de40f101ca --- /dev/null +++ b/core/src/main/java/org/keycloak/representations/idm/ClientRepresentation.java @@ -0,0 +1,218 @@ +package org.keycloak.representations.idm; + +import java.util.List; +import java.util.Map; + +/** + * @author Bill Burke + * @version $Revision: 1 $ + */ +public class ClientRepresentation { + protected String id; + protected String clientId; + protected String adminUrl; + protected String baseUrl; + protected Boolean surrogateAuthRequired; + protected Boolean enabled; + protected String secret; + protected String[] defaultRoles; + protected List redirectUris; + protected List webOrigins; + protected Integer notBefore; + protected Boolean bearerOnly; + protected Boolean consentRequired; + protected Boolean directGrantsOnly; + protected Boolean publicClient; + protected Boolean frontchannelLogout; + protected String protocol; + protected Map attributes; + protected Boolean fullScopeAllowed; + protected Integer nodeReRegistrationTimeout; + protected Map registeredNodes; + protected List identityProviders; + protected List protocolMappers; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getClientId() { + return clientId; + } + + public void setClientId(String clientId) { + this.clientId = clientId; + } + + public Boolean isEnabled() { + return enabled; + } + + public void setEnabled(Boolean enabled) { + this.enabled = enabled; + } + + public Boolean isSurrogateAuthRequired() { + return surrogateAuthRequired; + } + + public void setSurrogateAuthRequired(Boolean surrogateAuthRequired) { + this.surrogateAuthRequired = surrogateAuthRequired; + } + + public String getAdminUrl() { + return adminUrl; + } + + public void setAdminUrl(String adminUrl) { + this.adminUrl = adminUrl; + } + + public String getBaseUrl() { + return baseUrl; + } + + public void setBaseUrl(String baseUrl) { + this.baseUrl = baseUrl; + } + + public String getSecret() { + return secret; + } + + public void setSecret(String secret) { + this.secret = secret; + } + + public List getRedirectUris() { + return redirectUris; + } + + public void setRedirectUris(List redirectUris) { + this.redirectUris = redirectUris; + } + + public List getWebOrigins() { + return webOrigins; + } + + public void setWebOrigins(List webOrigins) { + this.webOrigins = webOrigins; + } + + public String[] getDefaultRoles() { + return defaultRoles; + } + + public void setDefaultRoles(String[] defaultRoles) { + this.defaultRoles = defaultRoles; + } + + public Integer getNotBefore() { + return notBefore; + } + + public void setNotBefore(Integer notBefore) { + this.notBefore = notBefore; + } + + public Boolean isBearerOnly() { + return bearerOnly; + } + + public void setBearerOnly(Boolean bearerOnly) { + this.bearerOnly = bearerOnly; + } + + public Boolean isConsentRequired() { + return consentRequired; + } + + public void setConsentRequired(Boolean consentRequired) { + this.consentRequired = consentRequired; + } + + public Boolean getDirectGrantsOnly() { + return directGrantsOnly; + } + + public void setDirectGrantsOnly(Boolean directGrantsOnly) { + this.directGrantsOnly = directGrantsOnly; + } + + public Boolean isPublicClient() { + return publicClient; + } + + public void setPublicClient(Boolean publicClient) { + this.publicClient = publicClient; + } + + public Boolean isFullScopeAllowed() { + return fullScopeAllowed; + } + + public void setFullScopeAllowed(Boolean fullScopeAllowed) { + this.fullScopeAllowed = fullScopeAllowed; + } + + public String getProtocol() { + return protocol; + } + + public void setProtocol(String protocol) { + this.protocol = protocol; + } + + public Map getAttributes() { + return attributes; + } + + public void setAttributes(Map attributes) { + this.attributes = attributes; + } + + public Integer getNodeReRegistrationTimeout() { + return nodeReRegistrationTimeout; + } + + public void setNodeReRegistrationTimeout(Integer nodeReRegistrationTimeout) { + this.nodeReRegistrationTimeout = nodeReRegistrationTimeout; + } + + public Map getRegisteredNodes() { + return registeredNodes; + } + + public void setRegisteredNodes(Map registeredNodes) { + this.registeredNodes = registeredNodes; + } + + public Boolean isFrontchannelLogout() { + return frontchannelLogout; + } + + public void setFrontchannelLogout(Boolean frontchannelLogout) { + this.frontchannelLogout = frontchannelLogout; + } + + public List getIdentityProviders() { + return this.identityProviders; + } + + public void setIdentityProviders(List identityProviders) { + this.identityProviders = identityProviders; + } + + public List getProtocolMappers() { + return protocolMappers; + } + + public void setProtocolMappers(List protocolMappers) { + this.protocolMappers = protocolMappers; + } +} diff --git a/core/src/main/java/org/keycloak/representations/idm/MappingsRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/MappingsRepresentation.java index 8172a2a2db..b7e90b8c75 100755 --- a/core/src/main/java/org/keycloak/representations/idm/MappingsRepresentation.java +++ b/core/src/main/java/org/keycloak/representations/idm/MappingsRepresentation.java @@ -9,7 +9,7 @@ import java.util.Map; */ public class MappingsRepresentation { protected List realmMappings; - protected Map applicationMappings; + protected Map clientMappings; public List getRealmMappings() { return realmMappings; @@ -19,11 +19,11 @@ public class MappingsRepresentation { this.realmMappings = realmMappings; } - public Map getApplicationMappings() { - return applicationMappings; + public Map getClientMappings() { + return clientMappings; } - public void setApplicationMappings(Map applicationMappings) { - this.applicationMappings = applicationMappings; + public void setClientMappings(Map clientMappings) { + this.clientMappings = clientMappings; } } diff --git a/core/src/main/java/org/keycloak/representations/idm/OAuthClientRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/OAuthClientRepresentation.java index 5f0ed4e3b0..9eec3e9d30 100755 --- a/core/src/main/java/org/keycloak/representations/idm/OAuthClientRepresentation.java +++ b/core/src/main/java/org/keycloak/representations/idm/OAuthClientRepresentation.java @@ -1,157 +1,9 @@ package org.keycloak.representations.idm; -import java.util.List; -import java.util.Map; - /** * @author Bill Burke * @version $Revision: 1 $ */ -public class OAuthClientRepresentation { - protected String id; - protected String name; - protected List redirectUris; - protected List webOrigins; - protected Boolean enabled; - protected String secret; - @Deprecated - protected ClaimRepresentation claims; - protected Integer notBefore; - protected Boolean publicClient; - protected String protocol; - protected Map attributes; - protected Boolean directGrantsOnly; - protected Boolean fullScopeAllowed; - protected Boolean frontchannelLogout; - protected List protocolMappers; - private List identityProviders; - - - 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 Boolean isEnabled() { - return enabled; - } - - public void setEnabled(Boolean enabled) { - this.enabled = enabled; - } - - public List getRedirectUris() { - return redirectUris; - } - - public void setRedirectUris(List redirectUris) { - this.redirectUris = redirectUris; - } - - public List getWebOrigins() { - return webOrigins; - } - - public void setWebOrigins(List webOrigins) { - this.webOrigins = webOrigins; - } - - public String getSecret() { - return secret; - } - - public void setSecret(String secret) { - this.secret = secret; - } - - public ClaimRepresentation getClaims() { - return claims; - } - - public void setClaims(ClaimRepresentation claims) { - this.claims = claims; - } - - public Integer getNotBefore() { - return notBefore; - } - - public void setNotBefore(Integer notBefore) { - this.notBefore = notBefore; - } - - public Boolean isPublicClient() { - return publicClient; - } - - public void setPublicClient(Boolean publicClient) { - this.publicClient = publicClient; - } - - public Boolean isDirectGrantsOnly() { - return directGrantsOnly; - } - - public void setDirectGrantsOnly(Boolean directGrantsOnly) { - this.directGrantsOnly = directGrantsOnly; - } - - public Boolean isFullScopeAllowed() { - return fullScopeAllowed; - } - - public void setFullScopeAllowed(Boolean fullScopeAllowed) { - this.fullScopeAllowed = fullScopeAllowed; - } - - public String getProtocol() { - return protocol; - } - - public void setProtocol(String protocol) { - this.protocol = protocol; - } - - public Map getAttributes() { - return attributes; - } - - public void setAttributes(Map attributes) { - this.attributes = attributes; - } - - public Boolean isFrontchannelLogout() { - return frontchannelLogout; - } - - public void setFrontchannelLogout(Boolean frontchannelLogout) { - this.frontchannelLogout = frontchannelLogout; - } - - public List getIdentityProviders() { - return this.identityProviders; - } - - public void setIdentityProviders(List identityProviders) { - this.identityProviders = identityProviders; - } - - public List getProtocolMappers() { - return protocolMappers; - } - - public void setProtocolMappers(List protocolMappers) { - this.protocolMappers = protocolMappers; - } +@Deprecated +public class OAuthClientRepresentation extends ApplicationRepresentation { } diff --git a/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java index b350e3825a..cbd5a777ce 100755 --- a/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java +++ b/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java @@ -25,13 +25,6 @@ public class RealmRepresentation { protected Boolean verifyEmail; protected Boolean resetPasswordAllowed; - @Deprecated - protected Boolean social; - @Deprecated - protected Boolean updateProfileOnInitialSocialLogin; - @Deprecated - protected Map socialProviders; - protected Boolean userCacheEnabled; protected Boolean realmCacheEnabled; @@ -55,9 +48,8 @@ public class RealmRepresentation { protected String passwordPolicy; protected List users; protected List scopeMappings; - protected Map> applicationScopeMappings; - protected List applications; - protected List oauthClients; + protected Map> clientScopeMappings; + protected List clients; protected Map browserSecurityHeaders; protected Map smtpServer; protected List userFederationProviders; @@ -76,6 +68,18 @@ public class RealmRepresentation { protected Set supportedLocales; protected String defaultLocale; + @Deprecated + protected Boolean social; + @Deprecated + protected Boolean updateProfileOnInitialSocialLogin; + @Deprecated + protected Map socialProviders; + @Deprecated + protected Map> applicationScopeMappings; + @Deprecated + protected List applications; + @Deprecated + protected List oauthClients; public String getId() { return id; @@ -101,14 +105,6 @@ public class RealmRepresentation { return applications; } - public ApplicationRepresentation resource(String name) { - ApplicationRepresentation resource = new ApplicationRepresentation(); - if (applications == null) applications = new ArrayList(); - applications.add(resource); - resource.setName(name); - return resource; - } - public void setUsers(List users) { this.users = users; } @@ -121,8 +117,12 @@ public class RealmRepresentation { return user; } - public void setApplications(List applications) { - this.applications = applications; + public List getClients() { + return clients; + } + + public void setClients(List clients) { + this.clients = clients; } public Boolean isEnabled() { @@ -321,22 +321,16 @@ public class RealmRepresentation { this.resetPasswordAllowed = resetPassword; } + @Deprecated public Boolean isSocial() { return social; } - public void setSocial(Boolean social) { - this.social = social; - } - + @Deprecated public Boolean isUpdateProfileOnInitialSocialLogin() { return updateProfileOnInitialSocialLogin; } - public void setUpdateProfileOnInitialSocialLogin(Boolean updateProfileOnInitialSocialLogin) { - this.updateProfileOnInitialSocialLogin = updateProfileOnInitialSocialLogin; - } - public Map getBrowserSecurityHeaders() { return browserSecurityHeaders; } @@ -345,14 +339,11 @@ public class RealmRepresentation { this.browserSecurityHeaders = browserSecurityHeaders; } + @Deprecated public Map getSocialProviders() { return socialProviders; } - public void setSocialProviders(Map socialProviders) { - this.socialProviders = socialProviders; - } - public Map getSmtpServer() { return smtpServer; } @@ -361,22 +352,24 @@ public class RealmRepresentation { this.smtpServer = smtpServer; } + @Deprecated public List getOauthClients() { return oauthClients; } - public void setOauthClients(List oauthClients) { - this.oauthClients = oauthClients; + public Map> getClientScopeMappings() { + return clientScopeMappings; } + public void setClientScopeMappings(Map> clientScopeMappings) { + this.clientScopeMappings = clientScopeMappings; + } + + @Deprecated public Map> getApplicationScopeMappings() { return applicationScopeMappings; } - public void setApplicationScopeMappings(Map> applicationScopeMappings) { - this.applicationScopeMappings = applicationScopeMappings; - } - public RolesRepresentation getRoles() { return roles; } diff --git a/core/src/main/java/org/keycloak/representations/idm/RoleRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/RoleRepresentation.java index 34ea91f841..9d0909d770 100755 --- a/core/src/main/java/org/keycloak/representations/idm/RoleRepresentation.java +++ b/core/src/main/java/org/keycloak/representations/idm/RoleRepresentation.java @@ -17,9 +17,10 @@ public class RoleRepresentation { public static class Composites { protected Set realm; + protected Map> client; + @Deprecated protected Map> application; - public Set getRealm() { return realm; } @@ -28,12 +29,17 @@ public class RoleRepresentation { this.realm = realm; } - public Map> getApplication() { - return application; + public Map> getClient() { + return client; } - public void setApplication(Map> application) { - this.application = application; + public void setClient(Map> client) { + this.client = client; + } + + @Deprecated + public Map> getApplication() { + return application; } } diff --git a/core/src/main/java/org/keycloak/representations/idm/RolesRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/RolesRepresentation.java index 496f7385bb..afeb96afd5 100755 --- a/core/src/main/java/org/keycloak/representations/idm/RolesRepresentation.java +++ b/core/src/main/java/org/keycloak/representations/idm/RolesRepresentation.java @@ -9,6 +9,8 @@ import java.util.Map; */ public class RolesRepresentation { protected List realm; + protected Map> client; + @Deprecated protected Map> application; public List getRealm() { @@ -19,11 +21,16 @@ public class RolesRepresentation { this.realm = realm; } + public Map> getClient() { + return client; + } + + public void setClient(Map> client) { + this.client = client; + } + + @Deprecated public Map> getApplication() { return application; } - - public void setApplication(Map> application) { - this.application = application; - } } diff --git a/core/src/main/java/org/keycloak/representations/idm/UserRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/UserRepresentation.java index d2907d54a6..94a90d9e45 100755 --- a/core/src/main/java/org/keycloak/representations/idm/UserRepresentation.java +++ b/core/src/main/java/org/keycloak/representations/idm/UserRepresentation.java @@ -25,10 +25,13 @@ public class UserRepresentation { protected List credentials; protected List requiredActions; protected List federatedIdentities; + protected List realmRoles; + protected Map> clientRoles; + + @Deprecated + protected Map> applicationRoles; @Deprecated protected List socialLinks; - protected List realmRoles; - protected Map> applicationRoles; public String getSelf() { return self; @@ -165,12 +168,17 @@ public class UserRepresentation { this.realmRoles = realmRoles; } - public Map> getApplicationRoles() { - return applicationRoles; + public Map> getClientRoles() { + return clientRoles; } - public void setApplicationRoles(Map> applicationRoles) { - this.applicationRoles = applicationRoles; + public void setClientRoles(Map> clientRoles) { + this.clientRoles = clientRoles; + } + + @Deprecated + public Map> getApplicationRoles() { + return applicationRoles; } public String getFederationLink() { diff --git a/core/src/main/java/org/keycloak/representations/idm/UserSessionRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/UserSessionRepresentation.java index 3035d2dfe8..6701f6acfa 100755 --- a/core/src/main/java/org/keycloak/representations/idm/UserSessionRepresentation.java +++ b/core/src/main/java/org/keycloak/representations/idm/UserSessionRepresentation.java @@ -15,7 +15,6 @@ public class UserSessionRepresentation { private String ipAddress; private long start; private long lastAccess; - private Map applications = new HashMap(); private Map clients = new HashMap(); public String getId() { @@ -58,14 +57,6 @@ public class UserSessionRepresentation { this.lastAccess = lastAccess; } - public Map getApplications() { - return applications; - } - - public void setApplications(Map applications) { - this.applications = applications; - } - public Map getClients() { return clients; } diff --git a/core/src/main/java/org/keycloak/util/Time.java b/core/src/main/java/org/keycloak/util/Time.java index 7da54f1f27..a5334ddb03 100644 --- a/core/src/main/java/org/keycloak/util/Time.java +++ b/core/src/main/java/org/keycloak/util/Time.java @@ -17,6 +17,10 @@ public class Time { return new Date(((long) time ) * 1000); } + public static long toMillis(int time) { + return ((long) time) * 1000; + } + public static void setOffset(int offset) { Time.offset = offset; } diff --git a/dependencies/server-all/pom.xml b/dependencies/server-all/pom.xml index 9d8921f8ed..d124ea5447 100755 --- a/dependencies/server-all/pom.xml +++ b/dependencies/server-all/pom.xml @@ -144,34 +144,6 @@ keycloak-kerberos-federation ${project.version} - - org.picketlink - picketlink-common - - - org.picketlink - picketlink-idm-api - - - org.picketlink - picketlink-idm-impl - - - org.picketlink - picketlink-idm-simple-schema - - - - - org.keycloak - keycloak-picketlink-api - ${project.version} - - - org.keycloak - keycloak-picketlink-ldap - ${project.version} - diff --git a/distribution/modules/build.xml b/distribution/modules/build.xml index 9f65cb95d4..df4bef5917 100755 --- a/distribution/modules/build.xml +++ b/distribution/modules/build.xml @@ -259,14 +259,6 @@ - - - - - - - - diff --git a/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-ldap-federation/main/module.xml b/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-ldap-federation/main/module.xml index 29dfd9c7d7..5f88f37e82 100755 --- a/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-ldap-federation/main/module.xml +++ b/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-ldap-federation/main/module.xml @@ -10,14 +10,9 @@ - - - - - diff --git a/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-picketlink-api/main/module.xml b/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-picketlink-api/main/module.xml deleted file mode 100755 index b51112b48a..0000000000 --- a/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-picketlink-api/main/module.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-picketlink-ldap/main/module.xml b/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-picketlink-ldap/main/module.xml deleted file mode 100755 index 429188fbb2..0000000000 --- a/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-picketlink-ldap/main/module.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-server/main/module.xml b/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-server/main/module.xml index f553d24263..ddf24752d0 100755 --- a/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-server/main/module.xml +++ b/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-server/main/module.xml @@ -48,8 +48,6 @@ - - diff --git a/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-services/main/module.xml b/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-services/main/module.xml index 86e86f492e..9864a070c1 100755 --- a/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-services/main/module.xml +++ b/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-services/main/module.xml @@ -49,10 +49,8 @@ - - diff --git a/distribution/subsystem-war/src/main/webapp/WEB-INF/jboss-deployment-structure.xml b/distribution/subsystem-war/src/main/webapp/WEB-INF/jboss-deployment-structure.xml index 6caa2c81e5..aae18bf302 100755 --- a/distribution/subsystem-war/src/main/webapp/WEB-INF/jboss-deployment-structure.xml +++ b/distribution/subsystem-war/src/main/webapp/WEB-INF/jboss-deployment-structure.xml @@ -40,9 +40,6 @@ - - - diff --git a/docbook/reference/en/en-US/modules/identity-broker.xml b/docbook/reference/en/en-US/modules/identity-broker.xml index 397fd02ca5..4c1a3c2a2e 100755 --- a/docbook/reference/en/en-US/modules/identity-broker.xml +++ b/docbook/reference/en/en-US/modules/identity-broker.xml @@ -284,6 +284,15 @@ during the authentication process. + + + GUI order + + + Allows you to define order of the provider when shown on login page. + You can put number into this field, providers with lower numbers are shown first. + + diff --git a/docbook/reference/en/en-US/modules/themes.xml b/docbook/reference/en/en-US/modules/themes.xml index db3d659a48..cd59f382ad 100755 --- a/docbook/reference/en/en-US/modules/themes.xml +++ b/docbook/reference/en/en-US/modules/themes.xml @@ -80,7 +80,7 @@ [ To deploy a theme as a module you need to create an jar (it's basically just a zip with jar extension) with - the theme resources and a file META/keycloak-server.json that describes the themes contained + the theme resources and a file META/keycloak-themes.json that describes the themes contained in the archive. For example example-theme.jar with the contents: META-INF/keycloak-themes.json @@ -213,7 +213,7 @@ import=common/keycloak theme/example-theme/login/login.ftl theme/example-theme/login/resources/css/styles.css - The contents of META-INF/keycloak-server.json in this case would be: + The contents of META-INF/keycloak-themes.json in this case would be: [ -<%@ page import="org.keycloak.admin.client.resource.ApplicationsResource" %> +<%@ page import="org.keycloak.admin.client.resource.ClientsResource" %> <%@ page import="org.keycloak.representations.idm.ApplicationRepresentation" %> <%@ page import="org.keycloak.util.UriUtils" %> <%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1" %> @@ -13,7 +13,7 @@ String authServer = UriUtils.getOrigin(request.getRequestURL().toString()) + "/auth"; Keycloak keycloak = Keycloak.getInstance(authServer, "example", "examples-admin-client", "password", "examples-admin-client", "password"); - ApplicationsResource applications = keycloak.realm("example").applications(); + ClientsResource applications = keycloak.realm("example").applications(); out.println("

Applications

"); out.println("
    "); diff --git a/examples/basic-auth/basicauthrealm.json b/examples/basic-auth/basicauthrealm.json index f6bac20a5b..0ed1bf5606 100644 --- a/examples/basic-auth/basicauthrealm.json +++ b/examples/basic-auth/basicauthrealm.json @@ -24,7 +24,7 @@ "value" : "password" } ], "realmRoles": [ "user","admin" ], - "applicationRoles": { + "clientRoles": { "realm-management": [ "realm-admin" ] } } @@ -41,7 +41,7 @@ } ] }, - "applications": [ + "clients": [ { "name": "basic-auth-service", "enabled": true, diff --git a/examples/broker/facebook-authentication/facebook-identity-provider-realm.json b/examples/broker/facebook-authentication/facebook-identity-provider-realm.json index 32a370497a..cc8c636e63 100644 --- a/examples/broker/facebook-authentication/facebook-identity-provider-realm.json +++ b/examples/broker/facebook-authentication/facebook-identity-provider-realm.json @@ -17,7 +17,7 @@ "value" : "password" } ], "realmRoles": [ "user","admin" ], - "applicationRoles": { + "clientRoles": { "realm-management": [ "realm-admin" ] } } @@ -30,7 +30,7 @@ } ] }, - "applications": [ + "clients": [ { "name": "facebook-authentication", "enabled": true, diff --git a/examples/broker/google-authentication/google-identity-provider-realm.json b/examples/broker/google-authentication/google-identity-provider-realm.json index 8b4deef92b..a721e34b13 100644 --- a/examples/broker/google-authentication/google-identity-provider-realm.json +++ b/examples/broker/google-authentication/google-identity-provider-realm.json @@ -17,7 +17,7 @@ "value" : "password" } ], "realmRoles": [ "user","admin" ], - "applicationRoles": { + "clientRoles": { "realm-management": [ "realm-admin" ] } } @@ -30,7 +30,7 @@ } ] }, - "applications": [ + "clients": [ { "name": "google-authentication", "enabled": true, diff --git a/examples/broker/saml-broker-authentication/saml-broker-authentication-realm.json b/examples/broker/saml-broker-authentication/saml-broker-authentication-realm.json index f8fbc8a242..ad757ab414 100644 --- a/examples/broker/saml-broker-authentication/saml-broker-authentication-realm.json +++ b/examples/broker/saml-broker-authentication/saml-broker-authentication-realm.json @@ -17,7 +17,7 @@ "value" : "password" } ], "realmRoles": [ "user","admin" ], - "applicationRoles": { + "clientRoles": { "realm-management": [ "realm-admin" ] } } @@ -30,7 +30,7 @@ } ] }, - "applications": [ + "clients": [ { "name": "saml-broker-authentication", "enabled": true, diff --git a/examples/broker/saml-broker-authentication/saml-broker-realm.json b/examples/broker/saml-broker-authentication/saml-broker-realm.json index 7f1cde0b82..8d0bad467b 100644 --- a/examples/broker/saml-broker-authentication/saml-broker-realm.json +++ b/examples/broker/saml-broker-authentication/saml-broker-realm.json @@ -26,7 +26,7 @@ } ] }, - "applications": [ + "clients": [ { "name": "http://localhost:8080/auth/realms/saml-broker-authentication-realm", "protocol": "saml", diff --git a/examples/broker/twitter-authentication/twitter-identity-provider-realm.json b/examples/broker/twitter-authentication/twitter-identity-provider-realm.json index 4b709044c7..f9add02775 100644 --- a/examples/broker/twitter-authentication/twitter-identity-provider-realm.json +++ b/examples/broker/twitter-authentication/twitter-identity-provider-realm.json @@ -18,7 +18,7 @@ "value" : "password" } ], "realmRoles": [ "user","admin" ], - "applicationRoles": { + "clientRoles": { "realm-management": [ "realm-admin" ] } } @@ -31,7 +31,7 @@ } ] }, - "applications": [ + "clients": [ { "name": "twitter-authentication", "enabled": true, diff --git a/examples/cordova/example-realm.json b/examples/cordova/example-realm.json index f0d6ad282f..d07a5d38a9 100755 --- a/examples/cordova/example-realm.json +++ b/examples/cordova/example-realm.json @@ -18,7 +18,7 @@ "value" : "password" } ], "realmRoles": [ "user" ], - "applicationRoles": { + "clientRoles": { "account": ["view-profile", "manage-account"] } } @@ -41,7 +41,7 @@ "roles": ["user"] } ], - "applications": [ + "clients": [ { "name": "cordova", "enabled": true, @@ -50,7 +50,7 @@ "webOrigins": ["localhost"] } ], - "applicationScopeMappings": { + "clientScopeMappings": { "account": [ { "client": "cordova", diff --git a/examples/cors/cors-realm.json b/examples/cors/cors-realm.json index ab08ee39e7..9e59580675 100755 --- a/examples/cors/cors-realm.json +++ b/examples/cors/cors-realm.json @@ -23,7 +23,7 @@ "value" : "password" } ], "realmRoles": [ "user" ], - "applicationRoles": { + "clientRoles": { "realm-management": [ "realm-admin" ] } } @@ -42,7 +42,7 @@ "roles": ["user"] } ], - "applications": [ + "clients": [ { "name": "angular-cors-product", "enabled": true, @@ -56,7 +56,7 @@ ] } ], - "applicationScopeMappings": { + "clientScopeMappings": { "realm-management": [ { "client": "angular-cors-product", diff --git a/examples/demo-template/testrealm.json b/examples/demo-template/testrealm.json index 031e20bc54..4b4d669fd6 100755 --- a/examples/demo-template/testrealm.json +++ b/examples/demo-template/testrealm.json @@ -24,7 +24,7 @@ "value" : "password" } ], "realmRoles": [ "user" ], - "applicationRoles": { + "clientRoles": { "account": [ "manage-account" ] } }, @@ -39,7 +39,7 @@ "value" : "password" } ], "realmRoles": [ "user" ], - "applicationRoles": { + "clientRoles": { "account": [ "manage-account" ] } }, @@ -54,7 +54,7 @@ "value" : "password" } ], "realmRoles": [ "user" ], - "applicationRoles": { + "clientRoles": { "account": [ "manage-account" ] } }, @@ -69,7 +69,7 @@ "value" : "password" } ], "realmRoles": [ "user","admin" ], - "applicationRoles": { + "clientRoles": { "realm-management": [ "realm-admin" ] } } @@ -92,7 +92,7 @@ "roles": ["user"] } ], - "applications": [ + "clients": [ { "name": "customer-portal", "enabled": true, @@ -146,12 +146,11 @@ "adminUrl": "/database", "baseUrl": "/database", "bearerOnly": true - } - ], - "oauthClients": [ + }, { "name": "third-party", "enabled": true, + "consentRequired": true, "redirectUris": [ "/oauth-client/*", "/oauth-client-cdi/*" @@ -162,11 +161,11 @@ "name": "admin-client", "enabled": true, "publicClient": true, - "directGrantsOnly": true - + "directGrantsOnly": true, + "consentRequired": true } ], - "applicationScopeMappings": { + "clientScopeMappings": { "realm-management": [ { "client": "admin-client", diff --git a/examples/fuse/testrealm.json b/examples/fuse/testrealm.json index 9ec73f9c73..d474e66de4 100644 --- a/examples/fuse/testrealm.json +++ b/examples/fuse/testrealm.json @@ -24,7 +24,7 @@ "value" : "password" } ], "realmRoles": [ "user" ], - "applicationRoles": { + "clientRoles": { "account": [ "manage-account" ] } }, @@ -39,7 +39,7 @@ "value" : "password" } ], "realmRoles": [ "user" ], - "applicationRoles": { + "clientRoles": { "account": [ "manage-account" ] } }, @@ -54,7 +54,7 @@ "value" : "password" } ], "realmRoles": [ "user" ], - "applicationRoles": { + "clientRoles": { "account": [ "manage-account" ] } }, @@ -69,7 +69,7 @@ "value" : "password" } ], "realmRoles": [ "user","admin" ], - "applicationRoles": { + "clientRoles": { "realm-management": [ "realm-admin" ] } }, @@ -84,7 +84,7 @@ "value" : "password" } ], "realmRoles": [ "user", "jmxAdmin" ], - "applicationRoles": { + "clientRoles": { "account": [ "manage-account" ], "realm-management": [ "realm-admin" ] } @@ -134,7 +134,7 @@ } ] }, - "applications": [ + "clients": [ { "name": "customer-portal", "enabled": true, @@ -178,14 +178,13 @@ "adminUrl": "http://localhost:8383/admin-camel-endpoint", "baseUrl": "http://localhost:8383/admin-camel-endpoint", "bearerOnly": true - } - ], - "oauthClients": [ + }, { "name": "ssh-jmx-admin-client", "enabled": true, "publicClient": false, "directGrantsOnly": true, + "consentRequired": true, "secret": "password" } ], diff --git a/examples/js-console/example-realm.json b/examples/js-console/example-realm.json index ddbb6eaf6a..81c92aa1f5 100755 --- a/examples/js-console/example-realm.json +++ b/examples/js-console/example-realm.json @@ -18,7 +18,7 @@ "value" : "password" } ], "realmRoles": [ "user" ], - "applicationRoles": { + "clientRoles": { "account": ["view-profile", "manage-account"] } } @@ -41,7 +41,7 @@ "roles": ["user"] } ], - "applications": [ + "clients": [ { "name": "js-console", "enabled": true, @@ -53,7 +53,7 @@ "webOrigins": [] } ], - "applicationScopeMappings": { + "clientScopeMappings": { "account": [ { "client": "js-console", diff --git a/examples/kerberos/kerberosrealm.json b/examples/kerberos/kerberosrealm.json index 4339e364a5..006961ca0d 100644 --- a/examples/kerberos/kerberosrealm.json +++ b/examples/kerberos/kerberosrealm.json @@ -13,7 +13,7 @@ "roles": [ "user" ] } ], - "applications": [ + "clients": [ { "name": "kerberos-app", "enabled": true, diff --git a/examples/multi-tenant/tenant1-realm.json b/examples/multi-tenant/tenant1-realm.json index e7a9cc9dfa..e759b12644 100644 --- a/examples/multi-tenant/tenant1-realm.json +++ b/examples/multi-tenant/tenant1-realm.json @@ -20,7 +20,7 @@ "value" : "user-tenant1" } ], "realmRoles": [ "user" ], - "applicationRoles": { + "clientRoles": { "multi-tenant": [ "user" ] } } @@ -40,7 +40,7 @@ } ], - "applications": [ + "clients": [ { "name": "multi-tenant", "enabled": true, diff --git a/examples/multi-tenant/tenant2-realm.json b/examples/multi-tenant/tenant2-realm.json index d628b731f1..2cd0e618cf 100644 --- a/examples/multi-tenant/tenant2-realm.json +++ b/examples/multi-tenant/tenant2-realm.json @@ -21,7 +21,7 @@ "value" : "user-tenant2" } ], "realmRoles": [ "user" ], - "applicationRoles": { + "clientRoles": { "multi-tenant": [ "user" ] } } @@ -41,9 +41,9 @@ } ], - "applications": [ + "clients": [ { - "name": "multi-tenant", + "clientId": "multi-tenant", "enabled": true, "adminUrl": "/multitenant/tenant2", "baseUrl": "/multitenant/tenant2", diff --git a/examples/saml/testsaml.json b/examples/saml/testsaml.json index b7f66af0de..7cf4a8ef52 100755 --- a/examples/saml/testsaml.json +++ b/examples/saml/testsaml.json @@ -25,9 +25,9 @@ "realmRoles": ["manager"] } ], - "applications": [ + "clients": [ { - "name": "http://localhost:8080/sales-post/", + "clientId": "http://localhost:8080/sales-post/", "enabled": true, "fullScopeAllowed": true, "protocol": "saml", @@ -41,7 +41,7 @@ } }, { - "name": "http://localhost:8080/sales-post-sig/", + "clientId": "http://localhost:8080/sales-post-sig/", "enabled": true, "protocol": "saml", "fullScopeAllowed": true, @@ -60,7 +60,7 @@ } }, { - "name": "http://localhost:8080/sales-post-enc/", + "clientId": "http://localhost:8080/sales-post-enc/", "enabled": true, "protocol": "saml", "fullScopeAllowed": true, @@ -82,7 +82,7 @@ } }, { - "name": "http://localhost:8080/employee/", + "clientId": "http://localhost:8080/employee/", "enabled": true, "fullScopeAllowed": true, "protocol": "saml", @@ -96,7 +96,7 @@ } }, { - "name": "http://localhost:8080/employee-sig/", + "clientId": "http://localhost:8080/employee-sig/", "enabled": true, "protocol": "saml", "fullScopeAllowed": true, diff --git a/export-import/export-import-api/src/main/java/org/keycloak/exportimport/util/ExportUtils.java b/export-import/export-import-api/src/main/java/org/keycloak/exportimport/util/ExportUtils.java index 9e683670c5..c404c3d3ad 100755 --- a/export-import/export-import-api/src/main/java/org/keycloak/exportimport/util/ExportUtils.java +++ b/export-import/export-import-api/src/main/java/org/keycloak/exportimport/util/ExportUtils.java @@ -6,10 +6,8 @@ import org.codehaus.jackson.JsonFactory; import org.codehaus.jackson.JsonGenerator; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.map.SerializationConfig; -import org.keycloak.models.ApplicationModel; import org.keycloak.models.ClientModel; import org.keycloak.models.KeycloakSession; -import org.keycloak.models.OAuthClientModel; import org.keycloak.models.RealmModel; import org.keycloak.models.RoleContainerModel; import org.keycloak.models.RoleModel; @@ -18,9 +16,8 @@ import org.keycloak.models.UserCredentialValueModel; import org.keycloak.models.UserModel; import org.keycloak.models.utils.ModelToRepresentation; import org.keycloak.representations.idm.ApplicationRepresentation; -import org.keycloak.representations.idm.ClaimRepresentation; +import org.keycloak.representations.idm.ClientRepresentation; import org.keycloak.representations.idm.CredentialRepresentation; -import org.keycloak.representations.idm.OAuthClientRepresentation; import org.keycloak.representations.idm.RealmRepresentation; import org.keycloak.representations.idm.RoleRepresentation; import org.keycloak.representations.idm.RolesRepresentation; @@ -57,52 +54,41 @@ public class ExportUtils { rep.setEventsListeners(new LinkedList(realm.getEventsListeners())); } - // Applications - List applications = realm.getApplications(); - List appReps = new ArrayList(); - for (ApplicationModel app : applications) { - ApplicationRepresentation appRep = exportApplication(app); - appReps.add(appRep); + // Clients + List clients = realm.getClients(); + List clientReps = new ArrayList<>(); + for (ClientModel app : clients) { + ClientRepresentation clientRep = exportClient(app); + clientReps.add(clientRep); } - rep.setApplications(appReps); - - // OAuth clients - List oauthClients = realm.getOAuthClients(); - List oauthClientReps = new ArrayList(); - for (OAuthClientModel oauthClient : oauthClients) { - OAuthClientRepresentation clientRep = ModelToRepresentation.toRepresentation(oauthClient); - clientRep.setSecret(oauthClient.getSecret()); - oauthClientReps.add(clientRep); - } - rep.setOauthClients(oauthClientReps); + rep.setClients(clientReps); // Roles List realmRoleReps = null; - Map> appRolesReps = new HashMap>(); + Map> clientRolesReps = new HashMap<>(); Set realmRoles = realm.getRoles(); if (realmRoles != null && realmRoles.size() > 0) { realmRoleReps = exportRoles(realmRoles); } - for (ApplicationModel app : applications) { - Set currentAppRoles = app.getRoles(); + for (ClientModel client : clients) { + Set currentAppRoles = client.getRoles(); List currentAppRoleReps = exportRoles(currentAppRoles); - appRolesReps.put(app.getName(), currentAppRoleReps); + clientRolesReps.put(client.getClientId(), currentAppRoleReps); } RolesRepresentation rolesRep = new RolesRepresentation(); if (realmRoleReps != null) { rolesRep.setRealm(realmRoleReps); } - if (appRolesReps.size() > 0) { - rolesRep.setApplication(appRolesReps); + if (clientRolesReps.size() > 0) { + rolesRep.setClient(clientRolesReps); } rep.setRoles(rolesRep); // Scopes - List allClients = new ArrayList(applications); - allClients.addAll(realm.getOAuthClients()); - Map> appScopeReps = new HashMap>(); + List allClients = new ArrayList<>(clients); + Map> clientScopeReps = new HashMap<>(); for (ClientModel client : allClients) { Set clientScopes = client.getScopeMappings(); @@ -114,12 +100,12 @@ public class ExportUtils { } scopeMappingRep.role(scope.getName()); } else { - ApplicationModel app = (ApplicationModel)scope.getContainer(); - String appName = app.getName(); - List currentAppScopes = appScopeReps.get(appName); + ClientModel app = (ClientModel)scope.getContainer(); + String appName = app.getClientId(); + List currentAppScopes = clientScopeReps.get(appName); if (currentAppScopes == null) { - currentAppScopes = new ArrayList(); - appScopeReps.put(appName, currentAppScopes); + currentAppScopes = new ArrayList<>(); + clientScopeReps.put(appName, currentAppScopes); } ScopeMappingRepresentation currentClientScope = null; @@ -139,8 +125,8 @@ public class ExportUtils { } } - if (appScopeReps.size() > 0) { - rep.setApplicationScopeMappings(appScopeReps); + if (clientScopeReps.size() > 0) { + rep.setClientScopeMappings(clientScopeReps); } // Finally users if needed @@ -162,14 +148,13 @@ public class ExportUtils { /** * Full export of application including claims and secret - * @param app + * @param client * @return full ApplicationRepresentation */ - public static ApplicationRepresentation exportApplication(ApplicationModel app) { - ApplicationRepresentation appRep = ModelToRepresentation.toRepresentation(app); - - appRep.setSecret(app.getSecret()); - return appRep; + public static ClientRepresentation exportClient(ClientModel client) { + ClientRepresentation clientRep = ModelToRepresentation.toRepresentation(client); + clientRep.setSecret(client.getSecret()); + return clientRep; } public static List exportRoles(Collection roles) { @@ -201,27 +186,27 @@ public class ExportUtils { Set composites = role.getComposites(); if (composites != null && composites.size() > 0) { Set compositeRealmRoles = null; - Map> compositeAppRoles = null; + Map> compositeClientRoles = null; for (RoleModel composite : composites) { RoleContainerModel crContainer = composite.getContainer(); if (crContainer instanceof RealmModel) { if (compositeRealmRoles == null) { - compositeRealmRoles = new HashSet(); + compositeRealmRoles = new HashSet<>(); } compositeRealmRoles.add(composite.getName()); } else { - if (compositeAppRoles == null) { - compositeAppRoles = new HashMap>(); + if (compositeClientRoles == null) { + compositeClientRoles = new HashMap<>(); } - ApplicationModel app = (ApplicationModel)crContainer; - String appName = app.getName(); - List currentAppComposites = compositeAppRoles.get(appName); + ClientModel app = (ClientModel)crContainer; + String appName = app.getClientId(); + List currentAppComposites = compositeClientRoles.get(appName); if (currentAppComposites == null) { - currentAppComposites = new ArrayList(); - compositeAppRoles.put(appName, currentAppComposites); + currentAppComposites = new ArrayList<>(); + compositeClientRoles.put(appName, currentAppComposites); } currentAppComposites.add(composite.getName()); } @@ -231,8 +216,8 @@ public class ExportUtils { if (compositeRealmRoles != null) { compRep.setRealm(compositeRealmRoles); } - if (compositeAppRoles != null) { - compRep.setApplication(compositeAppRoles); + if (compositeClientRoles != null) { + compRep.setClient(compositeClientRoles); } roleRep.setComposites(compRep); @@ -263,29 +248,29 @@ public class ExportUtils { // Role mappings Set roles = user.getRoleMappings(); - List realmRoleNames = new ArrayList(); - Map> appRoleNames = new HashMap>(); + List realmRoleNames = new ArrayList<>(); + Map> clientRoleNames = new HashMap<>(); for (RoleModel role : roles) { if (role.getContainer() instanceof RealmModel) { realmRoleNames.add(role.getName()); } else { - ApplicationModel app = (ApplicationModel)role.getContainer(); - String appName = app.getName(); - List currentAppRoles = appRoleNames.get(appName); - if (currentAppRoles == null) { - currentAppRoles = new ArrayList(); - appRoleNames.put(appName, currentAppRoles); + ClientModel client = (ClientModel)role.getContainer(); + String clientId = client.getClientId(); + List currentClientRoles = clientRoleNames.get(clientId); + if (currentClientRoles == null) { + currentClientRoles = new ArrayList<>(); + clientRoleNames.put(clientId, currentClientRoles); } - currentAppRoles.add(role.getName()); + currentClientRoles.add(role.getName()); } } if (realmRoleNames.size() > 0) { userRep.setRealmRoles(realmRoleNames); } - if (appRoleNames.size() > 0) { - userRep.setApplicationRoles(appRoleNames); + if (clientRoleNames.size() > 0) { + userRep.setClientRoles(clientRoleNames); } // Credentials diff --git a/export-import/export-import-api/src/main/java/org/keycloak/exportimport/util/ImportUtils.java b/export-import/export-import-api/src/main/java/org/keycloak/exportimport/util/ImportUtils.java index 5c0a60c890..66b106cc04 100755 --- a/export-import/export-import-api/src/main/java/org/keycloak/exportimport/util/ImportUtils.java +++ b/export-import/export-import-api/src/main/java/org/keycloak/exportimport/util/ImportUtils.java @@ -8,7 +8,7 @@ import org.jboss.logging.Logger; import org.keycloak.Config; import org.keycloak.exportimport.Strategy; import org.keycloak.models.AdminRoles; -import org.keycloak.models.ApplicationModel; +import org.keycloak.models.ClientModel; import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; import org.keycloak.models.RealmProvider; @@ -54,7 +54,7 @@ public class ImportUtils { if (Config.getAdminRealm().equals(realm.getId())) { // Delete all masterAdmin apps due to foreign key constraints for (RealmModel currRealm : model.getRealms()) { - currRealm.setMasterAdminApp(null); + currRealm.setMasterAdminClient(null); } } // TODO: For migration between versions, it should be possible to delete just realm but keep it's users @@ -81,9 +81,9 @@ public class ImportUtils { // We just imported master realm. All 'masterAdminApps' need to be refreshed RealmModel adminRealm = realm; for (RealmModel currentRealm : model.getRealms()) { - ApplicationModel masterApp = adminRealm.getApplicationByName(KeycloakModelUtils.getMasterRealmAdminApplicationName(currentRealm)); + ClientModel masterApp = adminRealm.getClientByClientId(KeycloakModelUtils.getMasterRealmAdminApplicationClientId(currentRealm)); if (masterApp != null) { - currentRealm.setMasterAdminApp(masterApp); + currentRealm.setMasterAdminClient(masterApp); } else { setupMasterAdminManagement(model, currentRealm); } @@ -91,9 +91,9 @@ public class ImportUtils { } else { // Need to refresh masterApp for current realm RealmModel adminRealm = model.getRealm(adminRealmId); - ApplicationModel masterApp = adminRealm.getApplicationByName(KeycloakModelUtils.getMasterRealmAdminApplicationName(realm)); + ClientModel masterApp = adminRealm.getClientByClientId(KeycloakModelUtils.getMasterRealmAdminApplicationClientId(realm)); if (masterApp != null) { - realm.setMasterAdminApp(masterApp); + realm.setMasterAdminClient(masterApp); } else { setupMasterAdminManagement(model, realm); } @@ -119,9 +119,9 @@ public class ImportUtils { } adminRole.setDescription("${role_"+AdminRoles.ADMIN+"}"); - ApplicationModel realmAdminApp = KeycloakModelUtils.createApplication(adminRealm, KeycloakModelUtils.getMasterRealmAdminApplicationName(realm)); + ClientModel realmAdminApp = KeycloakModelUtils.createClient(adminRealm, KeycloakModelUtils.getMasterRealmAdminApplicationClientId(realm)); realmAdminApp.setBearerOnly(true); - realm.setMasterAdminApp(realmAdminApp); + realm.setMasterAdminClient(realmAdminApp); for (String r : AdminRoles.ALL_REALM_ROLES) { RoleModel role = realmAdminApp.addRole(r); @@ -220,7 +220,7 @@ public class ImportUtils { private static void importUsers(KeycloakSession session, RealmProvider model, String realmName, List userReps) { RealmModel realm = model.getRealmByName(realmName); - Map apps = realm.getApplicationNameMap(); + Map apps = realm.getClientNameMap(); for (UserRepresentation user : userReps) { RepresentationToModel.createUser(session, realm, user, apps); } diff --git a/federation/ldap/pom.xml b/federation/ldap/pom.xml index a48b36daef..72803ab6e6 100755 --- a/federation/ldap/pom.xml +++ b/federation/ldap/pom.xml @@ -31,12 +31,6 @@ ${project.version} provided - - org.keycloak - keycloak-picketlink-api - ${project.version} - provided - org.jboss.resteasy resteasy-jaxrs @@ -61,27 +55,6 @@ jboss-logging provided - - - org.picketlink - picketlink-common - provided - - - org.picketlink - picketlink-idm-api - provided - - - org.picketlink - picketlink-idm-impl - provided - - - org.picketlink - picketlink-idm-simple-schema - provided - diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPFederationProvider.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPFederationProvider.java index f48880cfc9..370e0f07f8 100755 --- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPFederationProvider.java +++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPFederationProvider.java @@ -3,6 +3,10 @@ package org.keycloak.federation.ldap; import org.jboss.logging.Logger; import org.keycloak.federation.kerberos.impl.KerberosUsernamePasswordAuthenticator; import org.keycloak.federation.kerberos.impl.SPNEGOAuthenticator; +import org.keycloak.federation.ldap.idm.model.LDAPUser; +import org.keycloak.federation.ldap.idm.query.IdentityQuery; +import org.keycloak.federation.ldap.idm.query.IdentityQueryBuilder; +import org.keycloak.federation.ldap.idm.store.ldap.LDAPIdentityStore; import org.keycloak.federation.ldap.kerberos.LDAPProviderKerberosConfig; import org.keycloak.models.CredentialValidationOutput; import org.keycloak.models.KeycloakSession; @@ -16,12 +20,6 @@ import org.keycloak.models.UserFederationProvider; import org.keycloak.models.UserFederationProviderModel; import org.keycloak.models.UserModel; import org.keycloak.constants.KerberosConstants; -import org.picketlink.idm.IdentityManagementException; -import org.picketlink.idm.IdentityManager; -import org.picketlink.idm.PartitionManager; -import org.picketlink.idm.model.basic.BasicModel; -import org.picketlink.idm.model.basic.User; -import org.picketlink.idm.query.IdentityQuery; import java.util.Arrays; import java.util.HashMap; @@ -38,23 +36,21 @@ import java.util.Set; */ public class LDAPFederationProvider implements UserFederationProvider { private static final Logger logger = Logger.getLogger(LDAPFederationProvider.class); - public static final String LDAP_ID = "LDAP_ID"; - public static final String SYNC_REGISTRATIONS = "syncRegistrations"; protected LDAPFederationProviderFactory factory; protected KeycloakSession session; protected UserFederationProviderModel model; - protected PartitionManager partitionManager; + protected LDAPIdentityStore ldapIdentityStore; protected EditMode editMode; protected LDAPProviderKerberosConfig kerberosConfig; protected final Set supportedCredentialTypes = new HashSet(); - public LDAPFederationProvider(LDAPFederationProviderFactory factory, KeycloakSession session, UserFederationProviderModel model, PartitionManager partitionManager) { + public LDAPFederationProvider(LDAPFederationProviderFactory factory, KeycloakSession session, UserFederationProviderModel model, LDAPIdentityStore ldapIdentityStore) { this.factory = factory; this.session = session; this.model = model; - this.partitionManager = partitionManager; + this.ldapIdentityStore = ldapIdentityStore; this.kerberosConfig = new LDAPProviderKerberosConfig(model); String editModeString = model.getConfig().get(LDAPConstants.EDIT_MODE); if (editModeString == null) { @@ -69,16 +65,6 @@ public class LDAPFederationProvider implements UserFederationProvider { } } - private ModelException convertIDMException(IdentityManagementException ie) { - Throwable realCause = ie; - while (realCause.getCause() != null) { - realCause = realCause.getCause(); - } - - // Use the message from the realCause - return new ModelException(realCause.getMessage(), ie); - } - public KeycloakSession getSession() { return session; } @@ -87,8 +73,8 @@ public class LDAPFederationProvider implements UserFederationProvider { return model; } - public PartitionManager getPartitionManager() { - return partitionManager; + public LDAPIdentityStore getLdapIdentityStore() { + return this.ldapIdentityStore; } @Override @@ -125,22 +111,18 @@ public class LDAPFederationProvider implements UserFederationProvider { @Override public boolean synchronizeRegistrations() { - return "true".equalsIgnoreCase(model.getConfig().get(SYNC_REGISTRATIONS)) && editMode == EditMode.WRITABLE; + return "true".equalsIgnoreCase(model.getConfig().get(LDAPConstants.SYNC_REGISTRATIONS)) && editMode == EditMode.WRITABLE; } @Override public UserModel register(RealmModel realm, UserModel user) { - if (editMode == EditMode.READ_ONLY || editMode == EditMode.UNSYNCED) throw new IllegalStateException("Registration is not supported by this ldap server");; + if (editMode == EditMode.READ_ONLY || editMode == EditMode.UNSYNCED) throw new IllegalStateException("Registration is not supported by this ldap server"); if (!synchronizeRegistrations()) throw new IllegalStateException("Registration is not supported by this ldap server"); - try { - User picketlinkUser = LDAPUtils.addUser(this.partitionManager, user.getUsername(), user.getFirstName(), user.getLastName(), user.getEmail()); - user.setAttribute(LDAP_ID, picketlinkUser.getId()); - return proxy(user); - } catch (IdentityManagementException ie) { - throw convertIDMException(ie); - } - + LDAPUser ldapUser = LDAPUtils.addUser(this.ldapIdentityStore, user.getUsername(), user.getFirstName(), user.getLastName(), user.getEmail()); + user.setAttribute(LDAPConstants.LDAP_ID, ldapUser.getId()); + user.setAttribute(LDAPConstants.LDAP_ENTRY_DN, ldapUser.getEntryDN()); + return proxy(user); } @Override @@ -150,58 +132,53 @@ public class LDAPFederationProvider implements UserFederationProvider { return false; } - try { - return LDAPUtils.removeUser(partitionManager, user.getUsername()); - } catch (IdentityManagementException ie) { - throw convertIDMException(ie); - } + return LDAPUtils.removeUser(this.ldapIdentityStore, user.getUsername()); } @Override public List searchByAttributes(Map attributes, RealmModel realm, int maxResults) { List searchResults =new LinkedList(); - try { - Map plUsers = searchPicketlink(attributes, maxResults); - for (User user : plUsers.values()) { - if (session.userStorage().getUserByUsername(user.getLoginName(), realm) == null) { - UserModel imported = importUserFromPicketlink(realm, user); - searchResults.add(imported); - } + + Map ldapUsers = searchLDAP(attributes, maxResults); + for (LDAPUser ldapUser : ldapUsers.values()) { + if (session.userStorage().getUserByUsername(ldapUser.getLoginName(), realm) == null) { + UserModel imported = importUserFromLDAP(realm, ldapUser); + searchResults.add(imported); } - } catch (IdentityManagementException ie) { - throw convertIDMException(ie); } + return searchResults; } - protected Map searchPicketlink(Map attributes, int maxResults) { - IdentityManager identityManager = getIdentityManager(); - Map results = new HashMap(); + protected Map searchLDAP(Map attributes, int maxResults) { + + Map results = new HashMap(); if (attributes.containsKey(USERNAME)) { - User user = BasicModel.getUser(identityManager, attributes.get(USERNAME)); + LDAPUser user = LDAPUtils.getUser(this.ldapIdentityStore, attributes.get(USERNAME)); if (user != null) { results.put(user.getLoginName(), user); } } if (attributes.containsKey(EMAIL)) { - User user = queryByEmail(identityManager, attributes.get(EMAIL)); + LDAPUser user = queryByEmail(attributes.get(EMAIL)); if (user != null) { results.put(user.getLoginName(), user); } } if (attributes.containsKey(FIRST_NAME) || attributes.containsKey(LAST_NAME)) { - IdentityQuery query = identityManager.createIdentityQuery(User.class); + IdentityQueryBuilder queryBuilder = this.ldapIdentityStore.createQueryBuilder(); + IdentityQuery query = queryBuilder.createIdentityQuery(LDAPUser.class); if (attributes.containsKey(FIRST_NAME)) { - query.setParameter(User.FIRST_NAME, attributes.get(FIRST_NAME)); + query.where(queryBuilder.equal(LDAPUser.FIRST_NAME, attributes.get(FIRST_NAME))); } if (attributes.containsKey(LAST_NAME)) { - query.setParameter(User.LAST_NAME, attributes.get(LAST_NAME)); + query.where(queryBuilder.equal(LDAPUser.LAST_NAME, attributes.get(LAST_NAME))); } query.setLimit(maxResults); - List agents = query.getResultList(); - for (User user : agents) { + List users = query.getResultList(); + for (LDAPUser user : users) { results.put(user.getLoginName(), user); } } @@ -211,85 +188,69 @@ public class LDAPFederationProvider implements UserFederationProvider { @Override public boolean isValid(UserModel local) { - try { - User picketlinkUser = LDAPUtils.getUser(partitionManager, local.getUsername()); - if (picketlinkUser == null) { - return false; - } - return picketlinkUser.getId().equals(local.getAttribute(LDAP_ID)); - } catch (IdentityManagementException ie) { - throw convertIDMException(ie); + LDAPUser ldapUser = LDAPUtils.getUser(this.ldapIdentityStore, local.getUsername()); + if (ldapUser == null) { + return false; } + return ldapUser.getId().equals(local.getAttribute(LDAPConstants.LDAP_ID)); } @Override public UserModel getUserByUsername(RealmModel realm, String username) { - try { - User picketlinkUser = LDAPUtils.getUser(partitionManager, username); - if (picketlinkUser == null) { - return null; - } - - // KEYCLOAK-808: Should we allow case-sensitivity to be configurable? - if (!username.equals(picketlinkUser.getLoginName())) { - logger.warnf("User found in LDAP but with different username. LDAP username: %s, Searched username: %s", username, picketlinkUser.getLoginName()); - return null; - } - - return importUserFromPicketlink(realm, picketlinkUser); - } catch (IdentityManagementException ie) { - throw convertIDMException(ie); - } - } - - public IdentityManager getIdentityManager() { - return partitionManager.createIdentityManager(); - } - - protected UserModel importUserFromPicketlink(RealmModel realm, User picketlinkUser) { - String email = (picketlinkUser.getEmail() != null && picketlinkUser.getEmail().trim().length() > 0) ? picketlinkUser.getEmail() : null; - - if (picketlinkUser.getLoginName() == null) { - throw new ModelException("User returned from LDAP has null username! Check configuration of your LDAP mappings. ID of user from LDAP: " + picketlinkUser.getId()); + LDAPUser ldapUser = LDAPUtils.getUser(this.ldapIdentityStore, username); + if (ldapUser == null) { + return null; } - UserModel imported = session.userStorage().addUser(realm, picketlinkUser.getLoginName()); + // KEYCLOAK-808: Should we allow case-sensitivity to be configurable? + if (!username.equals(ldapUser.getLoginName())) { + logger.warnf("User found in LDAP but with different username. LDAP username: %s, Searched username: %s", username, ldapUser.getLoginName()); + return null; + } + + return importUserFromLDAP(realm, ldapUser); + } + + protected UserModel importUserFromLDAP(RealmModel realm, LDAPUser ldapUser) { + String email = (ldapUser.getEmail() != null && ldapUser.getEmail().trim().length() > 0) ? ldapUser.getEmail() : null; + + if (ldapUser.getLoginName() == null) { + throw new ModelException("User returned from LDAP has null username! Check configuration of your LDAP mappings. ID of user from LDAP: " + ldapUser.getId()); + } + + UserModel imported = session.userStorage().addUser(realm, ldapUser.getLoginName()); imported.setEnabled(true); imported.setEmail(email); - imported.setFirstName(picketlinkUser.getFirstName()); - imported.setLastName(picketlinkUser.getLastName()); + imported.setFirstName(ldapUser.getFirstName()); + imported.setLastName(ldapUser.getLastName()); imported.setFederationLink(model.getId()); - imported.setAttribute(LDAP_ID, picketlinkUser.getId()); + imported.setAttribute(LDAPConstants.LDAP_ID, ldapUser.getId()); + imported.setAttribute(LDAPConstants.LDAP_ENTRY_DN, ldapUser.getEntryDN()); - logger.debugf("Added new user from LDAP. Username: " + imported.getUsername() + ", Email: ", imported.getEmail() + ", LDAP_ID: " + picketlinkUser.getId()); + logger.debugf("Imported new user from LDAP to Keycloak DB. Username: [%s], Email: [%s], LDAP_ID: [%s], LDAP Entry DN: [%s]", imported.getUsername(), imported.getEmail(), + ldapUser.getId(), ldapUser.getEntryDN()); return proxy(imported); } - protected User queryByEmail(IdentityManager identityManager, String email) throws IdentityManagementException { - return LDAPUtils.getUserByEmail(identityManager, email); + protected LDAPUser queryByEmail(String email) { + return LDAPUtils.getUserByEmail(this.ldapIdentityStore, email); } @Override public UserModel getUserByEmail(RealmModel realm, String email) { - IdentityManager identityManager = getIdentityManager(); - - try { - User picketlinkUser = queryByEmail(identityManager, email); - if (picketlinkUser == null) { - return null; - } - - // KEYCLOAK-808: Should we allow case-sensitivity to be configurable? - if (!email.equals(picketlinkUser.getEmail())) { - logger.warnf("User found in LDAP but with different email. LDAP email: %s, Searched email: %s", email, picketlinkUser.getEmail()); - return null; - } - - return importUserFromPicketlink(realm, picketlinkUser); - } catch (IdentityManagementException ie) { - throw convertIDMException(ie); + LDAPUser ldapUser = queryByEmail(email); + if (ldapUser == null) { + return null; } + + // KEYCLOAK-808: Should we allow case-sensitivity to be configurable? + if (!email.equals(ldapUser.getEmail())) { + logger.warnf("User found in LDAP but with different email. LDAP email: %s, Searched email: %s", email, ldapUser.getEmail()); + return null; + } + + return importUserFromLDAP(realm, ldapUser); } @Override @@ -302,18 +263,14 @@ public class LDAPFederationProvider implements UserFederationProvider { // complete I don't think we have to do anything here } - public boolean validPassword(String username, String password) { + public boolean validPassword(UserModel user, String password) { if (kerberosConfig.isAllowKerberosAuthentication() && kerberosConfig.isUseKerberosForPasswordAuthentication()) { // Use Kerberos JAAS (Krb5LoginModule) KerberosUsernamePasswordAuthenticator authenticator = factory.createKerberosUsernamePasswordAuthenticator(kerberosConfig); - return authenticator.validUser(username, password); + return authenticator.validUser(user.getUsername(), password); } else { // Use Naming LDAP API - try { - return LDAPUtils.validatePassword(partitionManager, username, password); - } catch (IdentityManagementException ie) { - throw convertIDMException(ie); - } + return LDAPUtils.validatePassword(this.ldapIdentityStore, user, password); } } @@ -322,7 +279,7 @@ public class LDAPFederationProvider implements UserFederationProvider { public boolean validCredentials(RealmModel realm, UserModel user, List input) { for (UserCredentialModel cred : input) { if (cred.getType().equals(UserCredentialModel.PASSWORD)) { - return validPassword(user.getUsername(), cred.getValue()); + return validPassword(user, cred.getValue()); } else { return false; // invalid cred type } @@ -353,7 +310,7 @@ public class LDAPFederationProvider implements UserFederationProvider { UserModel user = findOrCreateAuthenticatedUser(realm, username); if (user == null) { - logger.warn("Kerberos/SPNEGO authentication succeeded with username [" + username + "], but couldn't find or create user with federation provider [" + model.getDisplayName() + "]"); + logger.warnf("Kerberos/SPNEGO authentication succeeded with username [%s], but couldn't find or create user with federation provider [%s]", username, model.getDisplayName()); return CredentialValidationOutput.failed(); } else { String delegationCredential = spnegoAuthenticator.getSerializedDelegationCredential(); @@ -375,24 +332,23 @@ public class LDAPFederationProvider implements UserFederationProvider { @Override public void close() { - //To change body of implemented methods use File | Settings | File Templates. } - protected void importPicketlinkUsers(RealmModel realm, List users, UserFederationProviderModel fedModel) { - for (User picketlinkUser : users) { - String username = picketlinkUser.getLoginName(); + protected void importLDAPUsers(RealmModel realm, List ldapUsers, UserFederationProviderModel fedModel) { + for (LDAPUser ldapUser : ldapUsers) { + String username = ldapUser.getLoginName(); UserModel currentUser = session.userStorage().getUserByUsername(username, realm); if (currentUser == null) { // Add new user to Keycloak - importUserFromPicketlink(realm, picketlinkUser); + importUserFromLDAP(realm, ldapUser); } else { - if ((fedModel.getId().equals(currentUser.getFederationLink())) && (picketlinkUser.getId().equals(currentUser.getAttribute(LDAPFederationProvider.LDAP_ID)))) { + if ((fedModel.getId().equals(currentUser.getFederationLink())) && (ldapUser.getId().equals(currentUser.getAttribute(LDAPConstants.LDAP_ID)))) { // Update keycloak user - String email = (picketlinkUser.getEmail() != null && picketlinkUser.getEmail().trim().length() > 0) ? picketlinkUser.getEmail() : null; + String email = (ldapUser.getEmail() != null && ldapUser.getEmail().trim().length() > 0) ? ldapUser.getEmail() : null; currentUser.setEmail(email); - currentUser.setFirstName(picketlinkUser.getFirstName()); - currentUser.setLastName(picketlinkUser.getLastName()); + currentUser.setFirstName(ldapUser.getFirstName()); + currentUser.setLastName(ldapUser.getLastName()); logger.debugf("Updated user from LDAP: %s", currentUser.getUsername()); } else { logger.warnf("User '%s' is not updated during sync as he is not linked to federation provider '%s'", username, fedModel.getDisplayName()); @@ -404,29 +360,29 @@ public class LDAPFederationProvider implements UserFederationProvider { /** * Called after successful kerberos authentication * - * @param realm + * @param realm realm * @param username username without realm prefix - * @return + * @return finded or newly created user */ protected UserModel findOrCreateAuthenticatedUser(RealmModel realm, String username) { UserModel user = session.userStorage().getUserByUsername(username, realm); if (user != null) { - logger.debug("Kerberos authenticated user " + username + " found in Keycloak storage"); + logger.debugf("Kerberos authenticated user [%s] found in Keycloak storage", username); if (!model.getId().equals(user.getFederationLink())) { - logger.warn("User with username " + username + " already exists, but is not linked to provider [" + model.getDisplayName() + "]"); + logger.warnf("User with username [%s] already exists, but is not linked to provider [%s]", username, model.getDisplayName()); return null; } else if (isValid(user)) { return proxy(user); } else { - logger.warn("User with username " + username + " already exists and is linked to provider [" + model.getDisplayName() + - "] but is not valid. Stale LDAP_ID on local user is: " + user.getAttribute(LDAP_ID)); + logger.warnf("User with username [%s] aready exists and is linked to provider [%s] but is not valid. Stale LDAP_ID on local user is: %s", + username, model.getDisplayName(), user.getAttribute(LDAPConstants.LDAP_ID)); logger.warn("Will re-create user"); session.userStorage().removeUser(realm, user); } } // Creating user to local storage - logger.debug("Kerberos authenticated user " + username + " not in Keycloak storage. Creating him"); + logger.debugf("Kerberos authenticated user [%s] not in Keycloak storage. Creating him", username); return getUserByUsername(realm, username); } } diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPFederationProviderFactory.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPFederationProviderFactory.java index c197052df9..a498a93b45 100755 --- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPFederationProviderFactory.java +++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPFederationProviderFactory.java @@ -3,10 +3,15 @@ package org.keycloak.federation.ldap; import org.jboss.logging.Logger; import org.keycloak.Config; import org.keycloak.federation.kerberos.CommonKerberosConfig; -import org.keycloak.federation.kerberos.KerberosConfig; import org.keycloak.federation.kerberos.impl.KerberosServerSubjectAuthenticator; import org.keycloak.federation.kerberos.impl.KerberosUsernamePasswordAuthenticator; import org.keycloak.federation.kerberos.impl.SPNEGOAuthenticator; +import org.keycloak.federation.ldap.idm.model.IdentityType; +import org.keycloak.federation.ldap.idm.model.LDAPUser; +import org.keycloak.federation.ldap.idm.query.Condition; +import org.keycloak.federation.ldap.idm.query.IdentityQuery; +import org.keycloak.federation.ldap.idm.query.IdentityQueryBuilder; +import org.keycloak.federation.ldap.idm.store.ldap.LDAPIdentityStore; import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSessionFactory; import org.keycloak.models.KeycloakSessionTask; @@ -16,16 +21,6 @@ import org.keycloak.models.UserFederationProvider; import org.keycloak.models.UserFederationProviderFactory; import org.keycloak.models.UserFederationProviderModel; import org.keycloak.models.utils.KeycloakModelUtils; -import org.keycloak.picketlink.PartitionManagerProvider; -import org.picketlink.idm.IdentityManager; -import org.picketlink.idm.PartitionManager; -import org.picketlink.idm.model.IdentityType; -import org.picketlink.idm.model.basic.User; -import org.picketlink.idm.query.AttributeParameter; -import org.picketlink.idm.query.Condition; -import org.picketlink.idm.query.IdentityQuery; -import org.picketlink.idm.query.IdentityQueryBuilder; -import org.picketlink.idm.query.QueryParameter; import java.util.Collections; import java.util.Date; @@ -41,6 +36,8 @@ public class LDAPFederationProviderFactory implements UserFederationProviderFact private static final Logger logger = Logger.getLogger(LDAPFederationProviderFactory.class); public static final String PROVIDER_NAME = "ldap"; + private LDAPIdentityStoreRegistry ldapStoreRegistry; + @Override public UserFederationProvider create(KeycloakSession session) { throw new IllegalAccessError("Illegal to call this method"); @@ -48,13 +45,13 @@ public class LDAPFederationProviderFactory implements UserFederationProviderFact @Override public LDAPFederationProvider getInstance(KeycloakSession session, UserFederationProviderModel model) { - PartitionManagerProvider idmProvider = session.getProvider(PartitionManagerProvider.class); - PartitionManager partition = idmProvider.getPartitionManager(model); - return new LDAPFederationProvider(this, session, model, partition); + LDAPIdentityStore ldapIdentityStore = this.ldapStoreRegistry.getLdapStore(model); + return new LDAPFederationProvider(this, session, model, ldapIdentityStore); } @Override public void init(Config.Scope config) { + this.ldapStoreRegistry = new LDAPIdentityStoreRegistry(); } @Override @@ -64,7 +61,7 @@ public class LDAPFederationProviderFactory implements UserFederationProviderFact @Override public void close() { - + this.ldapStoreRegistry = null; } @Override @@ -81,9 +78,8 @@ public class LDAPFederationProviderFactory implements UserFederationProviderFact public void syncAllUsers(KeycloakSessionFactory sessionFactory, String realmId, UserFederationProviderModel model) { logger.infof("Sync all users from LDAP to local store: realm: %s, federation provider: %s, current time: " + new Date(), realmId, model.getDisplayName()); - PartitionManagerProvider idmProvider = sessionFactory.create().getProvider(PartitionManagerProvider.class); - PartitionManager partitionMgr = idmProvider.getPartitionManager(model); - IdentityQuery userQuery = partitionMgr.createIdentityManager().createIdentityQuery(User.class); + LDAPIdentityStore ldapIdentityStore = this.ldapStoreRegistry.getLdapStore(model); + IdentityQuery userQuery = ldapIdentityStore.createQueryBuilder().createIdentityQuery(LDAPUser.class); syncImpl(sessionFactory, userQuery, realmId, model); // TODO: Remove all existing keycloak users, which have federation links, but are not in LDAP. Perhaps don't check users, which were just added or updated during this sync? @@ -91,26 +87,23 @@ public class LDAPFederationProviderFactory implements UserFederationProviderFact @Override public void syncChangedUsers(KeycloakSessionFactory sessionFactory, String realmId, UserFederationProviderModel model, Date lastSync) { - logger.infof("Sync changed users from LDAP to local store: realm: %s, federation provider: %s, current time: " + new Date() + ", last sync time: " + lastSync, realmId, model.getDisplayName()); + logger.infof("Sync changed users from LDAP to local store: realm: %s, federation provider: %s, current time: %s, last sync time: " + lastSync, realmId, model.getDisplayName(), new Date().toString()); - PartitionManagerProvider idmProvider = sessionFactory.create().getProvider(PartitionManagerProvider.class); - PartitionManager partitionMgr = idmProvider.getPartitionManager(model); + LDAPIdentityStore ldapIdentityStore = this.ldapStoreRegistry.getLdapStore(model); // Sync newly created users - IdentityManager identityManager = partitionMgr.createIdentityManager(); - IdentityQueryBuilder queryBuilder = identityManager.getQueryBuilder(); + IdentityQueryBuilder queryBuilder = ldapIdentityStore.createQueryBuilder(); Condition condition = queryBuilder.greaterThanOrEqualTo(IdentityType.CREATED_DATE, lastSync); - IdentityQuery userQuery = queryBuilder.createIdentityQuery(User.class).where(condition); + IdentityQuery userQuery = queryBuilder.createIdentityQuery(LDAPUser.class).where(condition); syncImpl(sessionFactory, userQuery, realmId, model); // Sync updated users - queryBuilder = identityManager.getQueryBuilder(); condition = queryBuilder.greaterThanOrEqualTo(LDAPUtils.MODIFY_DATE, lastSync); - userQuery = queryBuilder.createIdentityQuery(User.class).where(condition); + userQuery = queryBuilder.createIdentityQuery(LDAPUser.class).where(condition); syncImpl(sessionFactory, userQuery, realmId, model); } - protected void syncImpl(KeycloakSessionFactory sessionFactory, IdentityQuery userQuery, final String realmId, final UserFederationProviderModel fedModel) { + protected void syncImpl(KeycloakSessionFactory sessionFactory, IdentityQuery userQuery, final String realmId, final UserFederationProviderModel fedModel) { boolean pagination = Boolean.parseBoolean(fedModel.getConfig().get(LDAPConstants.PAGINATION)); if (pagination) { @@ -119,36 +112,36 @@ public class LDAPFederationProviderFactory implements UserFederationProviderFact boolean nextPage = true; while (nextPage) { userQuery.setLimit(pageSize); - final List users = userQuery.getResultList(); + final List users = userQuery.getResultList(); nextPage = userQuery.getPaginationContext() != null; KeycloakModelUtils.runJobInTransaction(sessionFactory, new KeycloakSessionTask() { @Override public void run(KeycloakSession session) { - importPicketlinkUsers(session, realmId, fedModel, users); + importLdapUsers(session, realmId, fedModel, users); } }); } } else { // LDAP pagination not available. Do everything in single transaction - final List users = userQuery.getResultList(); + final List users = userQuery.getResultList(); KeycloakModelUtils.runJobInTransaction(sessionFactory, new KeycloakSessionTask() { @Override public void run(KeycloakSession session) { - importPicketlinkUsers(session, realmId, fedModel, users); + importLdapUsers(session, realmId, fedModel, users); } }); } } - protected void importPicketlinkUsers(KeycloakSession session, String realmId, UserFederationProviderModel fedModel, List users) { + protected void importLdapUsers(KeycloakSession session, String realmId, UserFederationProviderModel fedModel, List ldapUsers) { RealmModel realm = session.realms().getRealm(realmId); LDAPFederationProvider ldapFedProvider = getInstance(session, fedModel); - ldapFedProvider.importPicketlinkUsers(realm, users, fedModel); + ldapFedProvider.importLDAPUsers(realm, ldapUsers, fedModel); } protected SPNEGOAuthenticator createSPNEGOAuthenticator(String spnegoToken, CommonKerberosConfig kerberosConfig) { diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPIdentityStoreRegistry.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPIdentityStoreRegistry.java new file mode 100644 index 0000000000..22aa55a6e9 --- /dev/null +++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPIdentityStoreRegistry.java @@ -0,0 +1,165 @@ +package org.keycloak.federation.ldap; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Properties; +import java.util.concurrent.ConcurrentHashMap; + +import org.jboss.logging.Logger; +import org.keycloak.federation.ldap.idm.model.LDAPUser; +import org.keycloak.federation.ldap.idm.store.ldap.LDAPIdentityStore; +import org.keycloak.federation.ldap.idm.store.ldap.LDAPIdentityStoreConfiguration; +import org.keycloak.federation.ldap.idm.store.ldap.LDAPMappingConfiguration; +import org.keycloak.models.LDAPConstants; +import org.keycloak.models.UserFederationProviderModel; + +/** + * @author Marek Posolda + */ +public class LDAPIdentityStoreRegistry { + + private static final Logger logger = Logger.getLogger(LDAPIdentityStoreRegistry.class); + + private Map ldapStores = new ConcurrentHashMap(); + + public LDAPIdentityStore getLdapStore(UserFederationProviderModel model) { + LDAPIdentityStoreContext context = ldapStores.get(model.getId()); + + // Ldap config might have changed for the realm. In this case, we must re-initialize + Map config = model.getConfig(); + if (context == null || !config.equals(context.config)) { + logLDAPConfig(model.getId(), config); + + LDAPIdentityStore store = createLdapIdentityStore(config); + context = new LDAPIdentityStoreContext(config, store); + ldapStores.put(model.getId(), context); + } + return context.store; + } + + // Don't log LDAP password + private void logLDAPConfig(String fedProviderId, Map ldapConfig) { + Map copy = new HashMap(ldapConfig); + copy.remove(LDAPConstants.BIND_CREDENTIAL); + logger.infof("Creating new LDAP based partition manager for the Federation provider: " + fedProviderId + ", LDAP Configuration: " + copy); + } + + /** + * @param ldapConfig from realm + * @return PartitionManager instance based on LDAP store + */ + public static LDAPIdentityStore createLdapIdentityStore(Map ldapConfig) { + Properties connectionProps = new Properties(); + if (ldapConfig.containsKey(LDAPConstants.CONNECTION_POOLING)) { + connectionProps.put("com.sun.jndi.ldap.connect.pool", ldapConfig.get(LDAPConstants.CONNECTION_POOLING)); + } + + checkSystemProperty("com.sun.jndi.ldap.connect.pool.authentication", "none simple"); + checkSystemProperty("com.sun.jndi.ldap.connect.pool.initsize", "1"); + checkSystemProperty("com.sun.jndi.ldap.connect.pool.maxsize", "1000"); + checkSystemProperty("com.sun.jndi.ldap.connect.pool.prefsize", "5"); + checkSystemProperty("com.sun.jndi.ldap.connect.pool.timeout", "300000"); + checkSystemProperty("com.sun.jndi.ldap.connect.pool.protocol", "plain"); + checkSystemProperty("com.sun.jndi.ldap.connect.pool.debug", "off"); + + String vendor = ldapConfig.get(LDAPConstants.VENDOR); + + boolean activeDirectory = vendor != null && vendor.equals(LDAPConstants.VENDOR_ACTIVE_DIRECTORY); + + String ldapLoginNameMapping = ldapConfig.get(LDAPConstants.USERNAME_LDAP_ATTRIBUTE); + if (ldapLoginNameMapping == null) { + ldapLoginNameMapping = activeDirectory ? LDAPConstants.CN : LDAPConstants.UID; + } + + String ldapFirstNameMapping = activeDirectory ? "givenName" : LDAPConstants.CN; + String createTimestampMapping = activeDirectory ? "whenCreated" : LDAPConstants.CREATE_TIMESTAMP; + String modifyTimestampMapping = activeDirectory ? "whenChanged" : LDAPConstants.MODIFY_TIMESTAMP; + String[] userObjectClasses = getUserObjectClasses(ldapConfig); + + boolean pagination = ldapConfig.containsKey(LDAPConstants.PAGINATION) ? Boolean.parseBoolean(ldapConfig.get(LDAPConstants.PAGINATION)) : false; + boolean userAccountControlsAfterPasswordUpdate = ldapConfig.containsKey(LDAPConstants.USER_ACCOUNT_CONTROLS_AFTER_PASSWORD_UPDATE) ? + Boolean.parseBoolean(ldapConfig.get(LDAPConstants.USER_ACCOUNT_CONTROLS_AFTER_PASSWORD_UPDATE)) : false; + + // Differences of unique attribute among various vendors + String uniqueIdentifierAttributeName = LDAPConstants.ENTRY_UUID; + if (vendor != null) { + switch (vendor) { + case LDAPConstants.VENDOR_RHDS: + uniqueIdentifierAttributeName = "nsuniqueid"; + break; + case LDAPConstants.VENDOR_TIVOLI: + uniqueIdentifierAttributeName = "uniqueidentifier"; + break; + case LDAPConstants.VENDOR_ACTIVE_DIRECTORY: + uniqueIdentifierAttributeName = LDAPConstants.OBJECT_GUID; + } + } + + LDAPIdentityStoreConfiguration ldapStoreConfig = new LDAPIdentityStoreConfiguration() + .setConnectionProperties(connectionProps) + .setBaseDN(ldapConfig.get(LDAPConstants.BASE_DN)) + .setBindDN(ldapConfig.get(LDAPConstants.BIND_DN)) + .setBindCredential(ldapConfig.get(LDAPConstants.BIND_CREDENTIAL)) + .setLdapURL(ldapConfig.get(LDAPConstants.CONNECTION_URL)) + .setActiveDirectory(activeDirectory) + .setPagination(pagination) + .setUniqueIdentifierAttributeName(uniqueIdentifierAttributeName) + .setFactoryName("com.sun.jndi.ldap.LdapCtxFactory") + .setAuthType("simple") + .setUserAccountControlsAfterPasswordUpdate(userAccountControlsAfterPasswordUpdate); + + LDAPMappingConfiguration ldapUserMappingConfig = ldapStoreConfig + .mappingConfig(LDAPUser.class) + .setBaseDN(ldapConfig.get(LDAPConstants.USER_DN_SUFFIX)) + .setObjectClasses(new HashSet(Arrays.asList(userObjectClasses))) + .setIdPropertyName("loginName") + .addAttributeMapping("loginName", ldapLoginNameMapping) + .addAttributeMapping("firstName", ldapFirstNameMapping) + .addAttributeMapping("lastName", LDAPConstants.SN) + .addAttributeMapping("email", LDAPConstants.EMAIL) + .addReadOnlyAttributeMapping("createdDate", createTimestampMapping) + .addReadOnlyAttributeMapping("modifyDate", modifyTimestampMapping); + + if (activeDirectory && ldapLoginNameMapping.equals("sAMAccountName")) { + ldapUserMappingConfig.setBindingPropertyName("fullName"); + ldapUserMappingConfig.addAttributeMapping("fullName", LDAPConstants.CN); + logger.infof("Using 'cn' attribute for DN of user and 'sAMAccountName' for username"); + } + + return new LDAPIdentityStore(ldapStoreConfig); + } + + private static void checkSystemProperty(String name, String defaultValue) { + if (System.getProperty(name) == null) { + System.setProperty(name, defaultValue); + } + } + + // Parse array of strings like [ "inetOrgPerson", "organizationalPerson" ] from the string like: "inetOrgPerson, organizationalPerson" + private static String[] getUserObjectClasses(Map ldapConfig) { + String objClassesCfg = ldapConfig.get(LDAPConstants.USER_OBJECT_CLASSES); + String objClassesStr = (objClassesCfg != null && objClassesCfg.length() > 0) ? objClassesCfg.trim() : "inetOrgPerson, organizationalPerson"; + + String[] objectClasses = objClassesStr.split(","); + + // Trim them + String[] userObjectClasses = new String[objectClasses.length]; + for (int i=0 ; i config, LDAPIdentityStore store) { + this.config = config; + this.store = store; + } + + private Map config; + private LDAPIdentityStore store; + } +} diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPUtils.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPUtils.java index db0e9b8ab1..97535926c9 100755 --- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPUtils.java +++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPUtils.java @@ -1,22 +1,21 @@ package org.keycloak.federation.ldap; +import org.keycloak.federation.ldap.idm.model.Attribute; +import org.keycloak.federation.ldap.idm.model.LDAPUser; +import org.keycloak.federation.ldap.idm.query.AttributeParameter; +import org.keycloak.federation.ldap.idm.query.IdentityQuery; +import org.keycloak.federation.ldap.idm.query.IdentityQueryBuilder; +import org.keycloak.federation.ldap.idm.query.QueryParameter; +import org.keycloak.federation.ldap.idm.store.ldap.LDAPIdentityStore; +import org.keycloak.models.LDAPConstants; import org.keycloak.models.ModelDuplicateException; -import org.picketlink.idm.IdentityManagementException; -import org.picketlink.idm.IdentityManager; -import org.picketlink.idm.PartitionManager; -import org.picketlink.idm.credential.Credentials; -import org.picketlink.idm.credential.Password; -import org.picketlink.idm.credential.UsernamePasswordCredentials; -import org.picketlink.idm.model.Attribute; -import org.picketlink.idm.model.basic.BasicModel; -import org.picketlink.idm.model.basic.User; -import org.picketlink.idm.query.AttributeParameter; -import org.picketlink.idm.query.QueryParameter; +import org.keycloak.models.UserModel; import java.util.List; /** - * Allow to directly call some operations against Picketlink IDM PartitionManager (hence LDAP). + * Allow to directly call some operations against LDAPIdentityStore. + * TODO: Is this class still needed? * * @author Marek Posolda */ @@ -24,99 +23,102 @@ public class LDAPUtils { public static QueryParameter MODIFY_DATE = new AttributeParameter("modifyDate"); - public static User addUser(PartitionManager partitionManager, String username, String firstName, String lastName, String email) { - IdentityManager identityManager = getIdentityManager(partitionManager); - - if (BasicModel.getUser(identityManager, username) != null) { + public static LDAPUser addUser(LDAPIdentityStore ldapIdentityStore, String username, String firstName, String lastName, String email) { + if (getUser(ldapIdentityStore, username) != null) { throw new ModelDuplicateException("User with same username already exists"); } - if (getUserByEmail(identityManager, email) != null) { + if (getUserByEmail(ldapIdentityStore, email) != null) { throw new ModelDuplicateException("User with same email already exists"); } - User picketlinkUser = new User(username); - picketlinkUser.setFirstName(firstName); - picketlinkUser.setLastName(lastName); - picketlinkUser.setEmail(email); - picketlinkUser.setAttribute(new Attribute("fullName", getFullName(username, firstName, lastName))); - identityManager.add(picketlinkUser); - return picketlinkUser; + LDAPUser ldapUser = new LDAPUser(username); + ldapUser.setFirstName(firstName); + ldapUser.setLastName(lastName); + ldapUser.setEmail(email); + ldapUser.setAttribute(new Attribute("fullName", getFullName(username, firstName, lastName))); + ldapIdentityStore.add(ldapUser); + return ldapUser; } - public static User updateUser(PartitionManager partitionManager, String username, String firstName, String lastName, String email) { - IdentityManager idmManager = getIdentityManager(partitionManager); - User picketlinkUser = BasicModel.getUser(idmManager, username); - picketlinkUser.setFirstName(firstName); - picketlinkUser.setLastName(lastName); - picketlinkUser.setEmail(email); - idmManager.update(picketlinkUser); - return picketlinkUser; + public static LDAPUser updateUser(LDAPIdentityStore ldapIdentityStore, String username, String firstName, String lastName, String email) { + LDAPUser ldapUser = getUser(ldapIdentityStore, username); + ldapUser.setFirstName(firstName); + ldapUser.setLastName(lastName); + ldapUser.setEmail(email); + ldapIdentityStore.update(ldapUser); + return ldapUser; } - public static void updatePassword(PartitionManager partitionManager, User picketlinkUser, String password) { - IdentityManager idmManager = getIdentityManager(partitionManager); - idmManager.updateCredential(picketlinkUser, new Password(password.toCharArray())); + public static void updatePassword(LDAPIdentityStore ldapIdentityStore, UserModel user, String password) { + LDAPUser ldapUser = convertUserForPasswordUpdate(user); + + ldapIdentityStore.updatePassword(ldapUser, password); } - public static boolean validatePassword(PartitionManager partitionManager, String username, String password) { - IdentityManager idmManager = getIdentityManager(partitionManager); + public static void updatePassword(LDAPIdentityStore ldapIdentityStore, LDAPUser user, String password) { + ldapIdentityStore.updatePassword(user, password); + } - UsernamePasswordCredentials credential = new UsernamePasswordCredentials(); - credential.setUsername(username); - credential.setPassword(new Password(password.toCharArray())); - idmManager.validateCredentials(credential); - if (credential.getStatus() == Credentials.Status.VALID) { - return true; - } else { - return false; + public static boolean validatePassword(LDAPIdentityStore ldapIdentityStore, UserModel user, String password) { + LDAPUser ldapUser = convertUserForPasswordUpdate(user); + + return ldapIdentityStore.validatePassword(ldapUser, password); + } + + public static boolean validatePassword(LDAPIdentityStore ldapIdentityStore, LDAPUser user, String password) { + return ldapIdentityStore.validatePassword(user, password); + } + + public static LDAPUser getUser(LDAPIdentityStore ldapIdentityStore, String username) { + return ldapIdentityStore.getUser(username); + } + + // Put just username and entryDN as these are needed by LDAPIdentityStore for passwordUpdate + private static LDAPUser convertUserForPasswordUpdate(UserModel kcUser) { + LDAPUser ldapUser = new LDAPUser(kcUser.getUsername()); + String ldapEntryDN = kcUser.getAttribute(LDAPConstants.LDAP_ENTRY_DN); + if (ldapEntryDN != null) { + ldapUser.setEntryDN(ldapEntryDN); } - } - - public static User getUser(PartitionManager partitionManager, String username) { - IdentityManager idmManager = getIdentityManager(partitionManager); - return BasicModel.getUser(idmManager, username); + return ldapUser; } - public static User getUserByEmail(IdentityManager idmManager, String email) throws IdentityManagementException { - List agents = idmManager.createIdentityQuery(User.class) - .setParameter(User.EMAIL, email).getResultList(); + public static LDAPUser getUserByEmail(LDAPIdentityStore ldapIdentityStore, String email) { + IdentityQueryBuilder queryBuilder = ldapIdentityStore.createQueryBuilder(); + IdentityQuery query = queryBuilder.createIdentityQuery(LDAPUser.class) + .where(queryBuilder.equal(LDAPUser.EMAIL, email)); + List users = query.getResultList(); - if (agents.isEmpty()) { + if (users.isEmpty()) { return null; - } else if (agents.size() == 1) { - return agents.get(0); + } else if (users.size() == 1) { + return users.get(0); } else { - throw new IdentityManagementException("Error - multiple users found with same email"); + throw new ModelDuplicateException("Error - multiple users found with same email " + email); } } - public static boolean removeUser(PartitionManager partitionManager, String username) { - IdentityManager idmManager = getIdentityManager(partitionManager); - User picketlinkUser = BasicModel.getUser(idmManager, username); - if (picketlinkUser == null) { + public static boolean removeUser(LDAPIdentityStore ldapIdentityStore, String username) { + LDAPUser ldapUser = getUser(ldapIdentityStore, username); + if (ldapUser == null) { return false; } - idmManager.remove(picketlinkUser); + ldapIdentityStore.remove(ldapUser); return true; } - public static void removeAllUsers(PartitionManager partitionManager) { - IdentityManager idmManager = getIdentityManager(partitionManager); - List users = idmManager.createIdentityQuery(User.class).getResultList(); + public static void removeAllUsers(LDAPIdentityStore ldapIdentityStore) { + List allUsers = getAllUsers(ldapIdentityStore); - for (User user : users) { - idmManager.remove(user); + for (LDAPUser user : allUsers) { + ldapIdentityStore.remove(user); } } - public static List getAllUsers(PartitionManager partitionManager) { - IdentityManager idmManager = getIdentityManager(partitionManager); - return idmManager.createIdentityQuery(User.class).getResultList(); - } - - private static IdentityManager getIdentityManager(PartitionManager partitionManager) { - return partitionManager.createIdentityManager(); + public static List getAllUsers(LDAPIdentityStore ldapIdentityStore) { + IdentityQuery userQuery = ldapIdentityStore.createQueryBuilder().createIdentityQuery(LDAPUser.class); + return userQuery.getResultList(); } // Needed for ActiveDirectory updates diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/WritableLDAPUserModelDelegate.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/WritableLDAPUserModelDelegate.java index 9a68f6a1ca..4debf0eaed 100755 --- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/WritableLDAPUserModelDelegate.java +++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/WritableLDAPUserModelDelegate.java @@ -1,16 +1,11 @@ package org.keycloak.federation.ldap; import org.jboss.logging.Logger; -import org.keycloak.models.ModelException; +import org.keycloak.federation.ldap.idm.model.LDAPUser; +import org.keycloak.federation.ldap.idm.store.ldap.LDAPIdentityStore; import org.keycloak.models.UserCredentialModel; import org.keycloak.models.UserModel; import org.keycloak.models.utils.UserModelDelegate; -import org.picketlink.idm.IdentityManagementException; -import org.picketlink.idm.IdentityManager; -import org.picketlink.idm.credential.Password; -import org.picketlink.idm.credential.TOTPCredential; -import org.picketlink.idm.model.basic.BasicModel; -import org.picketlink.idm.model.basic.User; /** * @author Bill Burke @@ -28,52 +23,43 @@ public class WritableLDAPUserModelDelegate extends UserModelDelegate implements @Override public void setUsername(String username) { - IdentityManager identityManager = provider.getIdentityManager(); + LDAPIdentityStore ldapIdentityStore = provider.getLdapIdentityStore(); - try { - User picketlinkUser = BasicModel.getUser(identityManager, delegate.getUsername()); - if (picketlinkUser == null) { - throw new IllegalStateException("User not found in LDAP storage!"); - } - picketlinkUser.setLoginName(username); - identityManager.update(picketlinkUser); - } catch (IdentityManagementException ie) { - throw new ModelException(ie); + LDAPUser ldapUser = LDAPUtils.getUser(ldapIdentityStore, delegate.getUsername()); + if (ldapUser == null) { + throw new IllegalStateException("User not found in LDAP storage!"); } + ldapUser.setLoginName(username); + ldapIdentityStore.update(ldapUser); + delegate.setUsername(username); } @Override public void setLastName(String lastName) { - IdentityManager identityManager = provider.getIdentityManager(); + LDAPIdentityStore ldapIdentityStore = provider.getLdapIdentityStore(); - try { - User picketlinkUser = BasicModel.getUser(identityManager, delegate.getUsername()); - if (picketlinkUser == null) { - throw new IllegalStateException("User not found in LDAP storage!"); - } - picketlinkUser.setLastName(lastName); - identityManager.update(picketlinkUser); - } catch (IdentityManagementException ie) { - throw new ModelException(ie); + LDAPUser ldapUser = LDAPUtils.getUser(ldapIdentityStore, delegate.getUsername()); + if (ldapUser == null) { + throw new IllegalStateException("User not found in LDAP storage!"); } + ldapUser.setLastName(lastName); + ldapIdentityStore.update(ldapUser); + delegate.setLastName(lastName); } @Override public void setFirstName(String first) { - IdentityManager identityManager = provider.getIdentityManager(); + LDAPIdentityStore ldapIdentityStore = provider.getLdapIdentityStore(); - try { - User picketlinkUser = BasicModel.getUser(identityManager, delegate.getUsername()); - if (picketlinkUser == null) { - throw new IllegalStateException("User not found in LDAP storage!"); - } - picketlinkUser.setFirstName(first); - identityManager.update(picketlinkUser); - } catch (IdentityManagementException ie) { - throw new ModelException(ie); + LDAPUser ldapUser = LDAPUtils.getUser(ldapIdentityStore, delegate.getUsername()); + if (ldapUser == null) { + throw new IllegalStateException("User not found in LDAP storage!"); } + ldapUser.setFirstName(first); + ldapIdentityStore.update(ldapUser); + delegate.setFirstName(first); } @@ -83,41 +69,31 @@ public class WritableLDAPUserModelDelegate extends UserModelDelegate implements delegate.updateCredential(cred); return; } - IdentityManager identityManager = provider.getIdentityManager(); - try { - User picketlinkUser = BasicModel.getUser(identityManager, getUsername()); - if (picketlinkUser == null) { - logger.debugf("User '%s' doesn't exists. Skip password update", getUsername()); - throw new IllegalStateException("User doesn't exist in LDAP storage"); - } - if (cred.getType().equals(UserCredentialModel.PASSWORD)) { - identityManager.updateCredential(picketlinkUser, new Password(cred.getValue().toCharArray())); - } else if (cred.getType().equals(UserCredentialModel.TOTP)) { - TOTPCredential credential = new TOTPCredential(cred.getValue()); - credential.setDevice(cred.getDevice()); - identityManager.updateCredential(picketlinkUser, credential); - } - } catch (IdentityManagementException ie) { - throw new ModelException(ie); + LDAPIdentityStore ldapIdentityStore = provider.getLdapIdentityStore(); + LDAPUser ldapUser = LDAPUtils.getUser(ldapIdentityStore, delegate.getUsername()); + if (ldapUser == null) { + throw new IllegalStateException("User " + delegate.getUsername() + " not found in LDAP storage!"); } + if (cred.getType().equals(UserCredentialModel.PASSWORD)) { + LDAPUtils.updatePassword(ldapIdentityStore, delegate, cred.getValue()); + } else { + logger.warnf("Don't know how to update credential of type [%s] for user [%s]", cred.getType(), delegate.getUsername()); + } } @Override public void setEmail(String email) { - IdentityManager identityManager = provider.getIdentityManager(); + LDAPIdentityStore ldapIdentityStore = provider.getLdapIdentityStore(); - try { - User picketlinkUser = BasicModel.getUser(identityManager, delegate.getUsername()); - if (picketlinkUser == null) { - throw new IllegalStateException("User not found in LDAP storage!"); - } - picketlinkUser.setEmail(email); - identityManager.update(picketlinkUser); - } catch (IdentityManagementException ie) { - throw new ModelException(ie); + LDAPUser ldapUser = LDAPUtils.getUser(ldapIdentityStore, delegate.getUsername()); + if (ldapUser == null) { + throw new IllegalStateException("User not found in LDAP storage!"); } + ldapUser.setEmail(email); + ldapIdentityStore.update(ldapUser); + delegate.setEmail(email); } diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/model/AbstractAttributedType.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/model/AbstractAttributedType.java new file mode 100644 index 0000000000..7e6d80b0f1 --- /dev/null +++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/model/AbstractAttributedType.java @@ -0,0 +1,85 @@ +package org.keycloak.federation.ldap.idm.model; + +import java.io.Serializable; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import static java.util.Collections.unmodifiableCollection; +import static java.util.Collections.unmodifiableMap; + +/** + * Abstract base class for all AttributedType implementations + * + * @author Shane Bryzak + * + */ +public abstract class AbstractAttributedType implements AttributedType { + private static final long serialVersionUID = -6118293036241099199L; + + private String id; + private String entryDN; + + private Map> attributes = + new HashMap>(); + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getEntryDN() { + return entryDN; + } + + public void setEntryDN(String entryDN) { + this.entryDN = entryDN; + } + + public void setAttribute(Attribute attribute) { + attributes.put(attribute.getName(), attribute); + } + + public void removeAttribute(String name) { + attributes.remove(name); + } + + @SuppressWarnings("unchecked") + public Attribute getAttribute(String name) { + return (Attribute) attributes.get(name); + } + + public Collection> getAttributes() { + return unmodifiableCollection(attributes.values()); + } + + public Map> getAttributesMap() { + return unmodifiableMap(attributes); + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + + if (!getClass().isInstance(obj)) { + return false; + } + + AttributedType other = (AttributedType) obj; + + return getId() != null && other.getId() != null && getId().equals(other.getId()); + } + + @Override + public int hashCode() { + int result = getId() != null ? getId().hashCode() : 0; + result = 31 * result + (getId() != null ? getId().hashCode() : 0); + return result; + } + +} \ No newline at end of file diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/model/AbstractIdentityType.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/model/AbstractIdentityType.java new file mode 100644 index 0000000000..8ee8bd6bd1 --- /dev/null +++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/model/AbstractIdentityType.java @@ -0,0 +1,70 @@ +package org.keycloak.federation.ldap.idm.model; + +import java.util.Date; + +/** + * Abstract base class for IdentityType implementations + * + * @author Shane Bryzak + */ +public abstract class AbstractIdentityType extends AbstractAttributedType implements IdentityType { + + private static final long serialVersionUID = 2843998332737143820L; + + private boolean enabled = true; + private Date createdDate = new Date(); + private Date expirationDate = null; + + public boolean isEnabled() { + return this.enabled; + } + + @Override + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + @Override + @AttributeProperty + public Date getExpirationDate() { + return this.expirationDate; + } + + @Override + public void setExpirationDate(Date expirationDate) { + this.expirationDate = expirationDate; + } + + @Override + @AttributeProperty + public Date getCreatedDate() { + return this.createdDate; + } + + @Override + public void setCreatedDate(Date createdDate) { + this.createdDate = createdDate; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + + if (!getClass().isInstance(obj)) { + return false; + } + + IdentityType other = (IdentityType) obj; + + return (getId() != null && other.getId() != null) + && (getId().equals(other.getId())); + } + + @Override + public int hashCode() { + return super.hashCode(); + } +} + diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/model/Attribute.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/model/Attribute.java new file mode 100644 index 0000000000..82dac06b87 --- /dev/null +++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/model/Attribute.java @@ -0,0 +1,80 @@ +package org.keycloak.federation.ldap.idm.model; + +import java.io.Serializable; + +/** + * Represents an attribute value, a type of metadata that can be associated with an IdentityType + * + * @author Shane Bryzak + * + * @param + */ +public class Attribute implements Serializable { + + private static final long serialVersionUID = 237211288303510728L; + + /** + * The name of the attribute + */ + private String name; + + /** + * The attribute value. + */ + private T value; + + /** + * Indicates whether this Attribute has a read-only value + */ + private boolean readOnly = false; + + /** + * Indicates whether the Attribute value has been loaded + */ + private boolean loaded = false; + + public Attribute(String name, T value) { + this.name = name; + this.value = value; + } + + public Attribute(String name, T value, boolean readOnly) { + this(name, value); + this.readOnly = readOnly; + } + + public String getName() { + return name; + } + + public T getValue() { + return value; + } + + public boolean isReadOnly() { + return readOnly; + } + + public boolean isLoaded() { + return loaded; + } + + public void setLoaded(boolean value) { + this.loaded = value; + } + + /** + * Sets the value for this attribute. If the Attribute value is readOnly, a RuntimeException is thrown. + * + * @param value + */ + public void setValue(T value) { + if (readOnly) { + throw new RuntimeException("Error setting Attribute value [" + name + " ] - value is read only."); + } + this.value = value; + } +} + + + diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/model/AttributeProperty.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/model/AttributeProperty.java new file mode 100644 index 0000000000..33b8706fca --- /dev/null +++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/model/AttributeProperty.java @@ -0,0 +1,31 @@ +package org.keycloak.federation.ldap.idm.model; + +import java.lang.annotation.Documented; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * Marks a property of an IdentityType, Partition or Relationship as being an attribute of that + * IdentityType, Partition or Relationship. + * + * @author Shane Bryzak + */ +@Target({METHOD, FIELD}) +@Documented +@Retention(RUNTIME) +@Inherited +public @interface AttributeProperty { + + /** + *

    Managed properties are stored as ad-hoc attributes and mapped from and to a specific property of a type.

    + * + * @return + */ + boolean managed() default false; + +} diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/model/AttributedType.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/model/AttributedType.java new file mode 100644 index 0000000000..5c374278c2 --- /dev/null +++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/model/AttributedType.java @@ -0,0 +1,75 @@ +package org.keycloak.federation.ldap.idm.model; + +import java.io.Serializable; +import java.util.Collection; + +import org.keycloak.federation.ldap.idm.query.AttributeParameter; +import org.keycloak.federation.ldap.idm.query.QueryParameter; + +/** + * + * @author Shane Bryzak + * + */ +public interface AttributedType extends Serializable { + + /** + * A query parameter used to set the id value. + */ + QueryParameter ID = new AttributeParameter("id"); + + /** + * Returns the unique identifier for this instance + * @return + */ + String getId(); + + /** + * Sets the unique identifier for this instance + * @return + */ + void setId(String id); + + /** + * Set the specified attribute. This operation will overwrite any previous value. + * + * @param attribute to be set + */ + void setAttribute(Attribute attribute); + + /** + * Remove the attribute with given name + * + * @param name of attribute + */ + void removeAttribute(String name); + + + // LDAP specific stuff + void setEntryDN(String entryDN); + String getEntryDN(); + + + /** + * Return the attribute value with the specified name + * + * @param name of attribute + * @return attribute value or null if attribute with given name doesn't exist. If given attribute has many values method + * will return first one + */ + Attribute getAttribute(String name); + + /** + * Returns a Map containing all attribute values for this IdentityType instance. + * + * @return map of attribute names and their values + */ + Collection> getAttributes(); + + public final class QUERY_ATTRIBUTE { + public static AttributeParameter byName(String name) { + return new AttributeParameter(name); + } + } +} + diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/model/IdentityType.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/model/IdentityType.java new file mode 100644 index 0000000000..f8ae8a1833 --- /dev/null +++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/model/IdentityType.java @@ -0,0 +1,100 @@ +package org.keycloak.federation.ldap.idm.model; + +import java.util.Date; + +import org.keycloak.federation.ldap.idm.query.AttributeParameter; +import org.keycloak.federation.ldap.idm.query.QueryParameter; + +/** + * This interface is the base for all identity model objects. It declares a number of + * properties that must be supported by all identity types, in addition to defining the API + * for identity attribute management. + * + * @author Shane Bryzak + */ +public interface IdentityType extends AttributedType { + + /** + * A query parameter used to set the enabled value. + */ + QueryParameter ENABLED = new AttributeParameter("enabled"); + + /** + * A query parameter used to set the createdDate value + */ + QueryParameter CREATED_DATE = new AttributeParameter("createdDate"); + + /** + * A query parameter used to set the created after date + */ + QueryParameter CREATED_AFTER = new AttributeParameter("createdDate"); + + /** + * A query parameter used to set the modified after date + */ + QueryParameter MODIFIED_AFTER = new AttributeParameter("modifyDate"); + + /** + * A query parameter used to set the created before date + */ + QueryParameter CREATED_BEFORE = new AttributeParameter("createdDate"); + + /** + * A query parameter used to set the expiryDate value + */ + QueryParameter EXPIRY_DATE = new AttributeParameter("expirationDate"); + + /** + * A query parameter used to set the expiration after date + */ + QueryParameter EXPIRY_AFTER = new AttributeParameter("expirationDate"); + + /** + * A query parameter used to set the expiration before date + */ + QueryParameter EXPIRY_BEFORE = new AttributeParameter("expirationDate"); + + /** + * Indicates the current enabled status of this IdentityType. + * + * @return A boolean value indicating whether this IdentityType is enabled. + */ + boolean isEnabled(); + + /** + *

    Sets the current enabled status of this {@link IdentityType}.

    + * + * @param enabled + */ + void setEnabled(boolean enabled); + + /** + * Returns the date that this IdentityType instance was created. + * + * @return Date value representing the creation date + */ + Date getCreatedDate(); + + /** + *

    Sets the date that this {@link IdentityType} was created.

    + * + * @param createdDate + */ + void setCreatedDate(Date createdDate); + + /** + * Returns the date that this IdentityType expires, or null if there is no expiry date. + * + * @return + */ + Date getExpirationDate(); + + /** + *

    Sets the date that this {@link IdentityType} expires.

    + * + * @param expirationDate + */ + void setExpirationDate(Date expirationDate); + +} + diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/model/LDAPUser.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/model/LDAPUser.java new file mode 100644 index 0000000000..4ce7ef9516 --- /dev/null +++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/model/LDAPUser.java @@ -0,0 +1,85 @@ +package org.keycloak.federation.ldap.idm.model; + + +import org.keycloak.federation.ldap.idm.query.QueryParameter; + +/** + * This class represents a User; a human agent that may authenticate with the application + * + * @author Shane Bryzak + */ +public class LDAPUser extends AbstractIdentityType { + + private static final long serialVersionUID = 4117586097100398485L; + + public static final QueryParameter LOGIN_NAME = AttributedType.QUERY_ATTRIBUTE.byName("loginName"); + + /** + * A query parameter used to set the firstName value. + */ + public static final QueryParameter FIRST_NAME = QUERY_ATTRIBUTE.byName("firstName"); + + /** + * A query parameter used to set the lastName value. + */ + public static final QueryParameter LAST_NAME = QUERY_ATTRIBUTE.byName("lastName"); + + /** + * A query parameter used to set the email value. + */ + public static final QueryParameter EMAIL = QUERY_ATTRIBUTE.byName("email"); + + @AttributeProperty + private String loginName; + + @AttributeProperty + private String firstName; + + @AttributeProperty + private String lastName; + + @AttributeProperty + private String email; + + public LDAPUser() { + + } + + public LDAPUser(String loginName) { + this.loginName = loginName; + } + + public String getLoginName() { + return loginName; + } + + public void setLoginName(String loginName) { + this.loginName = loginName; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public String getEmail() { + return this.email; + } + + public void setEmail(String email) { + this.email = email; + } + +} + diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/AttributeParameter.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/AttributeParameter.java new file mode 100644 index 0000000000..c5feea9319 --- /dev/null +++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/AttributeParameter.java @@ -0,0 +1,21 @@ +package org.keycloak.federation.ldap.idm.query; + +/** + *

    This class can be used to define a query parameter for properties annotated with + * {@link org.keycloak.federation.ldap.idm.model.AttributeProperty}. + *

    + * + * @author pedroigor + */ +public class AttributeParameter implements QueryParameter { + + private final String name; + + public AttributeParameter(String name) { + this.name = name; + } + + public String getName() { + return this.name; + } +} diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/Condition.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/Condition.java new file mode 100644 index 0000000000..85d81d8915 --- /dev/null +++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/Condition.java @@ -0,0 +1,18 @@ +package org.keycloak.federation.ldap.idm.query; + +/** + *

    A {@link Condition} is used to specify how a specific {@link QueryParameter} + * is defined in order to filter query results.

    + * + * @author Pedro Igor + */ +public interface Condition { + + /** + *

    The {@link QueryParameter} restricted by this condition.

    + * + * @return + */ + QueryParameter getParameter(); + +} \ No newline at end of file diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/IdentityQuery.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/IdentityQuery.java new file mode 100644 index 0000000000..1a77727fa8 --- /dev/null +++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/IdentityQuery.java @@ -0,0 +1,225 @@ +package org.keycloak.federation.ldap.idm.query; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.keycloak.federation.ldap.idm.model.IdentityType; + +/** + *

    An {@link IdentityQuery} is responsible for querying the underlying identity stores for instances of + * a given {@link IdentityType}.

    + * + *

    Instances of this class are obtained using the {@link IdentityQueryBuilder#createIdentityQuery(Class)} + * method.

    + * + *
    + *      IdentityManager identityManager = getIdentityManager();
    + *
    + *      // here we get the query builder
    + *      IdentityQueryBuilder builder = identityManager.getQueryBuilder();
    + *
    + *      // create a condition
    + *      Condition condition = builder.equal(User.LOGIN_NAME, "john");
    + *
    + *      // create a query for a specific identity type using the previously created condition
    + *      IdentityQuery query = builder.createIdentityQuery(User.class).where(condition);
    + *
    + *      // execute the query
    + *      List result = query.getResultList();
    + * 
    + * + *

    When preparing a query you may want to create conditions to filter its results and configure how they must be retrieved. + * For that, you can use the {@link IdentityQueryBuilder}, which provides useful methods for creating + * different expressions and conditions.

    + * + * @author Shane Bryzak + * @author Pedro Igor + */ +public interface IdentityQuery { + + /** + * @see #setPaginationContext(Object object) + */ + Object getPaginationContext(); + + /** + * Used for pagination models like LDAP when search will return some object (like cookie) for searching on next page + * + * @param object to be used for search next page + * + * @return this query + */ + IdentityQuery setPaginationContext(Object object); + + /** + * @deprecated Will be removed soon. + * + * @see #setSortParameters(QueryParameter...) + */ + @Deprecated + QueryParameter[] getSortParameters(); + + /** + * Parameters used to sort the results. First parameter has biggest priority. For example: setSortParameter(User.LAST_NAME, + * User.FIRST_NAME) means that results will be sorted primarily by lastName and firstName will be used to sort only records with + * same lastName + * + * @param sortParameters parameters to specify sort criteria + * + * @deprecated Use {@link IdentityQuery#sortBy(Sort...)} instead. Where you can create sort conditions + * from the {@link IdentityQueryBuilder}. + * + * @return this query + */ + @Deprecated + IdentityQuery setSortParameters(QueryParameter... sortParameters); + + /** + * @deprecated Use {@link IdentityQuery#getSorting()} for a list of sorting conditions. Will be removed soon. + * + * @return true if sorting will be ascending + * + * @see #setSortAscending(boolean) + */ + @Deprecated + boolean isSortAscending(); + + /** + * Specify if sorting will be ascending (true) or descending (false) + * + * @param sortAscending to specify if sorting will be ascending or descending + * + * @deprecated Use {@link IdentityQuery#sortBy(Sort...)} instead. Where you can create sort conditions + * from the {@link IdentityQueryBuilder}. + * + * @return this query + */ + @Deprecated + IdentityQuery setSortAscending(boolean sortAscending); + + /** + *

    Set a query parameter to this query in order to filter the results.

    + * + *

    This method always create an equality condition. For more conditions options take a look at {@link + * IdentityQueryBuilder} and use the {@link IdentityQuery#where(Condition...)} + * instead.

    + * + * @param param The query parameter. + * @param value The value to match for equality. + * + * @return + * + * @deprecated Use {@link IdentityQuery#where(Condition...)} to specify query conditions. + */ + @Deprecated + IdentityQuery setParameter(QueryParameter param, Object... value); + + /** + *

    Add to this query the conditions that will be used to filter results.

    + * + *

    Any condition previously added to this query will be preserved and the new conditions added. If you want to clear the + * conditions you must create a new query instance.

    + * + * @param condition One or more conditions created from {@link IdentityQueryBuilder}. + * + * @return + */ + IdentityQuery where(Condition... condition); + + /** + *

    Add to this query the sorting conditions to be applied to the results.

    + * + * @param sorts The ordering conditions. + * + * @return + */ + IdentityQuery sortBy(Sort... sorts); + + /** + *

    The type used to create this query.

    + * + * @return + */ + Class getIdentityType(); + + /** + *

    Returns a map with all the parameter set for this query.

    + * + * @return + * + * @deprecated Use {@link IdentityQuery#getConditions()} instead. Will be removed. + */ + @Deprecated + Map getParameters(); + + /** + *

    Returns a set containing all conditions used by this query to filter its results.

    + * + * @return + */ + Set getConditions(); + + /** + *

    Returns a set containing all sorting conditions used to filter the results.

    + * + * @return + */ + Set getSorting(); + + /** + *

    Returns the value used to restrict the given query parameter.

    + * + * @param queryParameter + * + * @return + */ + @Deprecated + Object[] getParameter(QueryParameter queryParameter); + + @Deprecated + Map getParameters(Class type); + + int getOffset(); + + /** + *

    Set the position of the first result to retrieve.

    + * + * @param offset + * + * @return + */ + IdentityQuery setOffset(int offset); + + /** + *

    Returns the number of instances to retrieve.

    + * + * @return + */ + int getLimit(); + + /** + *

    Set the maximum number of results to retrieve.

    + * + * @param limit the number of instances to retrieve. + * + * @return + */ + IdentityQuery setLimit(int limit); + + /** + *

    Execute the query against the underlying identity stores and returns a list containing all instances of + * the type (defined when creating this query instance) that match the conditions previously specified.

    + * + * @return + */ + List getResultList(); + + /** + * Count of all query results. It takes into account query parameters, but it doesn't take into account pagination parameter + * like offset and limit + * + * @return count of all query results + */ + int getResultCount(); +} diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/IdentityQueryBuilder.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/IdentityQueryBuilder.java new file mode 100644 index 0000000000..022063521b --- /dev/null +++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/IdentityQueryBuilder.java @@ -0,0 +1,124 @@ +package org.keycloak.federation.ldap.idm.query; + +import org.keycloak.federation.ldap.idm.model.IdentityType; + +/** + *

    The {@link IdentityQueryBuilder} is responsible for creating {@link IdentityQuery} instances and also + * provide methods to create conditions, orderings, sorting, etc.

    + * + * @author Pedro Igor + */ +public interface IdentityQueryBuilder { + + /** + *

    Create a condition for testing the whether the query parameter satisfies the given pattern..

    + * + * @param parameter The query parameter. + * @param pattern The pattern to match. + * + * @return + */ + Condition like(QueryParameter parameter, String pattern); + + /** + *

    Create a condition for testing the arguments for equality.

    + * + * @param parameter The query parameter. + * @param value The value to compare. + * + * @return + */ + Condition equal(QueryParameter parameter, Object value); + + /** + *

    Create a condition for testing whether the query parameter is grater than the given value..

    + * + * @param parameter The query parameter. + * @param x The value to compare. + * + * @return + */ + Condition greaterThan(QueryParameter parameter, Object x); + + /** + *

    Create a condition for testing whether the query parameter is grater than or equal to the given value..

    + * + * @param parameter The query parameter. + * @param x The value to compare. + * + * @return + */ + Condition greaterThanOrEqualTo(QueryParameter parameter, Object x); + + /** + *

    Create a condition for testing whether the query parameter is less than the given value..

    + * + * @param parameter The query parameter. + * @param x The value to compare. + * + * @return + */ + Condition lessThan(QueryParameter parameter, Object x); + + /** + *

    Create a condition for testing whether the query parameter is less than or equal to the given value..

    + * + * @param parameter The query parameter. + * @param x The value to compare. + * + * @return + */ + Condition lessThanOrEqualTo(QueryParameter parameter, Object x); + + /** + *

    Create a condition for testing whether the query parameter is between the given values.

    + * + * @param parameter The query parameter. + * @param x The first value. + * @param x The second value. + * + * @return + */ + Condition between(QueryParameter parameter, Object x, Object y); + + /** + *

    Create a condition for testing whether the query parameter is contained in a list of values.

    + * + * @param parameter The query parameter. + * @param values A list of values. + * + * @return + */ + Condition in(QueryParameter parameter, Object... values); + + /** + *

    Create an ascending order for the given parameter. Once created, you can use it to sort the results of a + * query.

    + * + * @param parameter The query parameter to sort. + * + * @return + */ + Sort asc(QueryParameter parameter); + + /** + *

    Create an descending order for the given parameter. Once created, you can use it to sort the results of a + * query.

    + * + * @param parameter The query parameter to sort. + * + * @return + */ + Sort desc(QueryParameter parameter); + + /** + *

    Create an {@link IdentityQuery} that can be used to query for {@link + * IdentityType} instances of a the given identityType.

    + * + * @param identityType The type to search. If you provide the {@link IdentityType} + * base interface any of its sub-types will be returned. + * + * @return + */ + IdentityQuery createIdentityQuery(Class identityType); +} diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/QueryParameter.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/QueryParameter.java new file mode 100644 index 0000000000..ae2bbdf910 --- /dev/null +++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/QueryParameter.java @@ -0,0 +1,12 @@ +package org.keycloak.federation.ldap.idm.query; + +/** + * A marker interface indicating that the implementing class can be used as a + * parameter within an IdentityQuery or RelationshipQuery + * + * @author Shane Bryzak + * + */ +public interface QueryParameter { + +} diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/Sort.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/Sort.java new file mode 100644 index 0000000000..dfd331ed59 --- /dev/null +++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/Sort.java @@ -0,0 +1,23 @@ +package org.keycloak.federation.ldap.idm.query; + +/** + * @author Pedro Igor + */ +public class Sort { + + private final QueryParameter parameter; + private final boolean asc; + + public Sort(QueryParameter parameter, boolean asc) { + this.parameter = parameter; + this.asc = asc; + } + + public QueryParameter getParameter() { + return this.parameter; + } + + public boolean isAscending() { + return asc; + } +} diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/BetweenCondition.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/BetweenCondition.java new file mode 100644 index 0000000000..672fdaa72b --- /dev/null +++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/BetweenCondition.java @@ -0,0 +1,33 @@ +package org.keycloak.federation.ldap.idm.query.internal; + +import org.keycloak.federation.ldap.idm.query.Condition; +import org.keycloak.federation.ldap.idm.query.QueryParameter; + +/** + * @author Pedro Igor + */ +public class BetweenCondition implements Condition { + + private final Comparable x; + private final Comparable y; + private final QueryParameter parameter; + + public BetweenCondition(QueryParameter parameter, Comparable x, Comparable y) { + this.parameter = parameter; + this.x = x; + this.y = y; + } + + @Override + public QueryParameter getParameter() { + return this.parameter; + } + + public Comparable getX() { + return this.x; + } + + public Comparable getY() { + return this.y; + } +} diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/DefaultIdentityQuery.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/DefaultIdentityQuery.java new file mode 100644 index 0000000000..21b02537da --- /dev/null +++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/DefaultIdentityQuery.java @@ -0,0 +1,207 @@ +package org.keycloak.federation.ldap.idm.query.internal; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.keycloak.federation.ldap.idm.model.IdentityType; +import org.keycloak.federation.ldap.idm.query.Condition; +import org.keycloak.federation.ldap.idm.query.IdentityQuery; +import org.keycloak.federation.ldap.idm.query.IdentityQueryBuilder; +import org.keycloak.federation.ldap.idm.query.QueryParameter; +import org.keycloak.federation.ldap.idm.query.Sort; +import org.keycloak.federation.ldap.idm.store.IdentityStore; +import org.keycloak.models.ModelException; + +import static java.util.Collections.unmodifiableSet; + +/** + * Default IdentityQuery implementation. + * + * @param + * + * @author Shane Bryzak + */ +public class DefaultIdentityQuery implements IdentityQuery { + + private final Map parameters = new LinkedHashMap(); + private final Class identityType; + private final IdentityStore identityStore; + private final IdentityQueryBuilder queryBuilder; + private int offset; + private int limit; + private Object paginationContext; + private QueryParameter[] sortParameters; + private boolean sortAscending = true; + private final Set conditions = new LinkedHashSet(); + private final Set ordering = new LinkedHashSet(); + + public DefaultIdentityQuery(IdentityQueryBuilder queryBuilder, Class identityType, IdentityStore identityStore) { + this.queryBuilder = queryBuilder; + this.identityStore = identityStore; + this.identityType = identityType; + } + + @Override + public IdentityQuery setParameter(QueryParameter queryParameter, Object... value) { + if (value == null || value.length == 0) { + throw new ModelException("Query Parameter values null or empty"); + } + + parameters.put(queryParameter, value); + + if (IdentityType.CREATED_AFTER.equals(queryParameter) || IdentityType.EXPIRY_AFTER.equals(queryParameter)) { + this.conditions.add(queryBuilder.greaterThanOrEqualTo(queryParameter, value[0])); + } else if (IdentityType.CREATED_BEFORE.equals(queryParameter) || IdentityType.EXPIRY_BEFORE.equals(queryParameter)) { + this.conditions.add(queryBuilder.lessThanOrEqualTo(queryParameter, value[0])); + } else { + this.conditions.add(queryBuilder.equal(queryParameter, value[0])); + } + + return this; + } + + @Override + public IdentityQuery where(Condition... condition) { + this.conditions.addAll(Arrays.asList(condition)); + return this; + } + + @Override + public IdentityQuery sortBy(Sort... sorts) { + this.ordering.addAll(Arrays.asList(sorts)); + return this; + } + + @Override + public Set getSorting() { + return unmodifiableSet(this.ordering); + } + + @Override + public Class getIdentityType() { + return identityType; + } + + @Override + public Map getParameters() { + return parameters; + } + + @Override + public Object[] getParameter(QueryParameter queryParameter) { + return this.parameters.get(queryParameter); + } + + @Override + public Map getParameters(Class type) { + Map typedParameters = new HashMap(); + + Set> entrySet = this.parameters.entrySet(); + + for (Map.Entry entry : entrySet) { + if (type.isInstance(entry.getKey())) { + typedParameters.put(entry.getKey(), entry.getValue()); + } + } + + return typedParameters; + } + + @Override + public int getLimit() { + return limit; + } + + @Override + public int getOffset() { + return offset; + } + + @Override + public Object getPaginationContext() { + return paginationContext; + } + + @Override + public QueryParameter[] getSortParameters() { + return sortParameters; + } + + @Override + public boolean isSortAscending() { + return sortAscending; + } + + @Override + public List getResultList() { + + // remove this statement once deprecated methods on IdentityQuery are removed + if (this.sortParameters != null) { + for (QueryParameter parameter : this.sortParameters) { + if (isSortAscending()) { + sortBy(this.queryBuilder.asc(parameter)); + } else { + sortBy(this.queryBuilder.desc(parameter)); + } + } + } + + List result = new ArrayList(); + + try { + for (T identityType : identityStore.fetchQueryResults(this)) { + result.add(identityType); + } + } catch (Exception e) { + throw new ModelException("LDAP Query failed", e); + } + + return result; + } + + @Override + public int getResultCount() { + return identityStore.countQueryResults(this); + } + + @Override + public IdentityQuery setOffset(int offset) { + this.offset = offset; + return this; + } + + @Override + public IdentityQuery setLimit(int limit) { + this.limit = limit; + return this; + } + + @Override + public IdentityQuery setSortParameters(QueryParameter... sortParameters) { + this.sortParameters = sortParameters; + return this; + } + + @Override + public IdentityQuery setSortAscending(boolean sortAscending) { + this.sortAscending = sortAscending; + return this; + } + + @Override + public IdentityQuery setPaginationContext(Object object) { + this.paginationContext = object; + return this; + } + + @Override + public Set getConditions() { + return unmodifiableSet(this.conditions); + } +} diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/DefaultQueryBuilder.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/DefaultQueryBuilder.java new file mode 100644 index 0000000000..5d3b72e165 --- /dev/null +++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/DefaultQueryBuilder.java @@ -0,0 +1,89 @@ +package org.keycloak.federation.ldap.idm.query.internal; + +import org.keycloak.federation.ldap.idm.model.IdentityType; +import org.keycloak.federation.ldap.idm.query.Condition; +import org.keycloak.federation.ldap.idm.query.IdentityQuery; +import org.keycloak.federation.ldap.idm.query.IdentityQueryBuilder; +import org.keycloak.federation.ldap.idm.query.QueryParameter; +import org.keycloak.federation.ldap.idm.query.Sort; +import org.keycloak.federation.ldap.idm.store.IdentityStore; +import org.keycloak.models.ModelException; + +/** + * @author Pedro Igor + */ +public class DefaultQueryBuilder implements IdentityQueryBuilder { + + private final IdentityStore identityStore; + + public DefaultQueryBuilder(IdentityStore identityStore) { + this.identityStore = identityStore; + } + + @Override + public Condition like(QueryParameter parameter, String pattern) { + return new LikeCondition(parameter, pattern); + } + + @Override + public Condition equal(QueryParameter parameter, Object value) { + return new EqualCondition(parameter, value); + } + + @Override + public Condition greaterThan(QueryParameter parameter, Object x) { + throwExceptionIfNotComparable(x); + return new GreaterThanCondition(parameter, (Comparable) x, false); + } + + @Override + public Condition greaterThanOrEqualTo(QueryParameter parameter, Object x) { + throwExceptionIfNotComparable(x); + return new GreaterThanCondition(parameter, (Comparable) x, true); + } + + @Override + public Condition lessThan(QueryParameter parameter, Object x) { + throwExceptionIfNotComparable(x); + return new LessThanCondition(parameter, (Comparable) x, false); + } + + @Override + public Condition lessThanOrEqualTo(QueryParameter parameter, Object x) { + throwExceptionIfNotComparable(x); + return new LessThanCondition(parameter, (Comparable) x, true); + } + + @Override + public Condition between(QueryParameter parameter, Object x, Object y) { + throwExceptionIfNotComparable(x); + throwExceptionIfNotComparable(y); + return new BetweenCondition(parameter, (Comparable) x, (Comparable) y); + } + + @Override + public Condition in(QueryParameter parameter, Object... x) { + return new InCondition(parameter, x); + } + + @Override + public Sort asc(QueryParameter parameter) { + return new Sort(parameter, true); + } + + @Override + public Sort desc(QueryParameter parameter) { + return new Sort(parameter, false); + } + + @Override + public IdentityQuery createIdentityQuery(Class identityType) { + return new DefaultIdentityQuery(this, identityType, this.identityStore); + } + + private void throwExceptionIfNotComparable(Object x) { + if (!Comparable.class.isInstance(x)) { + throw new ModelException("Query parameter value [" + x + "] must be " + Comparable.class + "."); + } + } +} \ No newline at end of file diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/EqualCondition.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/EqualCondition.java new file mode 100644 index 0000000000..a3fee26e13 --- /dev/null +++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/EqualCondition.java @@ -0,0 +1,36 @@ +package org.keycloak.federation.ldap.idm.query.internal; + +import org.keycloak.federation.ldap.idm.query.AttributeParameter; +import org.keycloak.federation.ldap.idm.query.Condition; +import org.keycloak.federation.ldap.idm.query.QueryParameter; + +/** + * @author Pedro Igor + */ +public class EqualCondition implements Condition { + + private final QueryParameter parameter; + private final Object value; + + public EqualCondition(QueryParameter parameter, Object value) { + this.parameter = parameter; + this.value = value; + } + + @Override + public QueryParameter getParameter() { + return this.parameter; + } + + public Object getValue() { + return this.value; + } + + @Override + public String toString() { + return "EqualCondition{" + + "parameter=" + ((AttributeParameter) parameter).getName() + + ", value=" + value + + '}'; + } +} diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/GreaterThanCondition.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/GreaterThanCondition.java new file mode 100644 index 0000000000..cbdf5407b6 --- /dev/null +++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/GreaterThanCondition.java @@ -0,0 +1,34 @@ +package org.keycloak.federation.ldap.idm.query.internal; + +import org.keycloak.federation.ldap.idm.query.Condition; +import org.keycloak.federation.ldap.idm.query.QueryParameter; + +/** + * @author Pedro Igor + */ +public class GreaterThanCondition implements Condition { + + private final boolean orEqual; + + private final QueryParameter parameter; + private final Comparable value; + + public GreaterThanCondition(QueryParameter parameter, Comparable value, boolean orEqual) { + this.parameter = parameter; + this.value = value; + this.orEqual = orEqual; + } + + @Override + public QueryParameter getParameter() { + return this.parameter; + } + + public Comparable getValue() { + return this.value; + } + + public boolean isOrEqual() { + return this.orEqual; + } +} \ No newline at end of file diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/InCondition.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/InCondition.java new file mode 100644 index 0000000000..54d22342a9 --- /dev/null +++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/InCondition.java @@ -0,0 +1,28 @@ +package org.keycloak.federation.ldap.idm.query.internal; + +import org.keycloak.federation.ldap.idm.query.Condition; +import org.keycloak.federation.ldap.idm.query.QueryParameter; + +/** + * @author Pedro Igor + */ +public class InCondition implements Condition { + + private final QueryParameter parameter; + private final Object[] value; + + public InCondition(QueryParameter parameter, Object[] value) { + this.parameter = parameter; + this.value = value; + } + + @Override + public QueryParameter getParameter() { + return this.parameter; + } + + public Object[] getValue() { + return this.value; + } +} + diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/LessThanCondition.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/LessThanCondition.java new file mode 100644 index 0000000000..5906a5ced0 --- /dev/null +++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/LessThanCondition.java @@ -0,0 +1,34 @@ +package org.keycloak.federation.ldap.idm.query.internal; + +import org.keycloak.federation.ldap.idm.query.Condition; +import org.keycloak.federation.ldap.idm.query.QueryParameter; + +/** + * @author Pedro Igor + */ +public class LessThanCondition implements Condition { + + private final boolean orEqual; + + private final QueryParameter parameter; + private final Comparable value; + + public LessThanCondition(QueryParameter parameter, Comparable value, boolean orEqual) { + this.parameter = parameter; + this.value = value; + this.orEqual = orEqual; + } + + @Override + public QueryParameter getParameter() { + return this.parameter; + } + + public Comparable getValue() { + return this.value; + } + + public boolean isOrEqual() { + return this.orEqual; + } +} diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/LikeCondition.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/LikeCondition.java new file mode 100644 index 0000000000..6c6810362b --- /dev/null +++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/LikeCondition.java @@ -0,0 +1,28 @@ +package org.keycloak.federation.ldap.idm.query.internal; + +import org.keycloak.federation.ldap.idm.query.Condition; +import org.keycloak.federation.ldap.idm.query.QueryParameter; + +/** + * @author Pedro Igor + */ +public class LikeCondition implements Condition { + + private final QueryParameter parameter; + private final Object value; + + public LikeCondition(QueryParameter parameter, Object value) { + this.parameter = parameter; + this.value = value; + } + + @Override + public QueryParameter getParameter() { + return this.parameter; + } + + public Object getValue() { + return this.value; + } + +} diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/store/IdentityStore.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/store/IdentityStore.java new file mode 100644 index 0000000000..7fef705c86 --- /dev/null +++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/store/IdentityStore.java @@ -0,0 +1,81 @@ +package org.keycloak.federation.ldap.idm.store; + +import java.util.List; + +import org.keycloak.federation.ldap.idm.model.AttributedType; +import org.keycloak.federation.ldap.idm.model.IdentityType; +import org.keycloak.federation.ldap.idm.model.LDAPUser; +import org.keycloak.federation.ldap.idm.query.IdentityQuery; +import org.keycloak.federation.ldap.idm.store.ldap.LDAPIdentityStoreConfiguration; + +/** + * IdentityStore representation providing minimal SPI + * + * TODO: Rather remove this abstraction + * + * @author Boleslaw Dawidowicz + * @author Shane Bryzak + */ +public interface IdentityStore { + + /** + * Returns the configuration for this IdentityStore instance + * + * @return + */ + LDAPIdentityStoreConfiguration getConfig(); + + // General + + /** + * Persists the specified IdentityType + * + * @param value + */ + void add(AttributedType value); + + /** + * Updates the specified IdentityType + * + * @param value + */ + void update(AttributedType value); + + /** + * Removes the specified IdentityType + * + * @param value + */ + void remove(AttributedType value); + + // Identity query + + List fetchQueryResults(IdentityQuery identityQuery); + + int countQueryResults(IdentityQuery identityQuery); + +// // Relationship query +// +// List fetchQueryResults(RelationshipQuery query); +// +// int countQueryResults(RelationshipQuery query); + + // Credentials + + /** + * Validates the specified credentials. + * + * @param user Keycloak user + * @param password Ldap password + */ + boolean validatePassword(LDAPUser user, String password); + + /** + * Updates the specified credential value. + * + * @param user Keycloak user + * @param password Ldap password + */ + void updatePassword(LDAPUser user, String password); + +} diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/store/ldap/LDAPIdentityStore.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/store/ldap/LDAPIdentityStore.java new file mode 100644 index 0000000000..8b912406ac --- /dev/null +++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/store/ldap/LDAPIdentityStore.java @@ -0,0 +1,761 @@ +package org.keycloak.federation.ldap.idm.store.ldap; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.NoSuchElementException; + +import javax.naming.NamingEnumeration; +import javax.naming.NamingException; +import javax.naming.directory.Attribute; +import javax.naming.directory.Attributes; +import javax.naming.directory.BasicAttribute; +import javax.naming.directory.BasicAttributes; +import javax.naming.directory.DirContext; +import javax.naming.directory.ModificationItem; +import javax.naming.directory.SearchResult; + +import org.jboss.logging.Logger; +import org.keycloak.federation.ldap.idm.model.AttributedType; +import org.keycloak.federation.ldap.idm.model.IdentityType; +import org.keycloak.federation.ldap.idm.model.LDAPUser; +import org.keycloak.federation.ldap.idm.query.AttributeParameter; +import org.keycloak.federation.ldap.idm.query.Condition; +import org.keycloak.federation.ldap.idm.query.IdentityQuery; +import org.keycloak.federation.ldap.idm.query.IdentityQueryBuilder; +import org.keycloak.federation.ldap.idm.query.QueryParameter; +import org.keycloak.federation.ldap.idm.query.internal.BetweenCondition; +import org.keycloak.federation.ldap.idm.query.internal.DefaultQueryBuilder; +import org.keycloak.federation.ldap.idm.query.internal.EqualCondition; +import org.keycloak.federation.ldap.idm.query.internal.GreaterThanCondition; +import org.keycloak.federation.ldap.idm.query.internal.InCondition; +import org.keycloak.federation.ldap.idm.query.internal.LessThanCondition; +import org.keycloak.federation.ldap.idm.query.internal.LikeCondition; +import org.keycloak.federation.ldap.idm.store.IdentityStore; +import org.keycloak.models.LDAPConstants; +import org.keycloak.models.ModelDuplicateException; +import org.keycloak.models.ModelException; +import org.keycloak.models.utils.reflection.NamedPropertyCriteria; +import org.keycloak.models.utils.reflection.Property; +import org.keycloak.models.utils.reflection.PropertyQueries; +import org.keycloak.models.utils.reflection.TypedPropertyCriteria; +import org.keycloak.util.reflections.Reflections; + +/** + * An IdentityStore implementation backed by an LDAP directory + * + * @author Shane Bryzak + * @author Anil Saldhana + * @author Pedro Silva + */ +public class LDAPIdentityStore implements IdentityStore { + + private static final Logger logger = Logger.getLogger(LDAPIdentityStore.class); + + public static final String EMPTY_ATTRIBUTE_VALUE = " "; + + private final LDAPIdentityStoreConfiguration config; + private final LDAPOperationManager operationManager; + + public LDAPIdentityStore(LDAPIdentityStoreConfiguration config) { + this.config = config; + + try { + this.operationManager = new LDAPOperationManager(getConfig()); + } catch (NamingException e) { + throw new ModelException("Couldn't init operation manager", e); + } + } + + @Override + public LDAPIdentityStoreConfiguration getConfig() { + return this.config; + } + + @Override + public void add(AttributedType attributedType) { + // id will be assigned by the ldap server + attributedType.setId(null); + + String entryDN = getBindingDN(attributedType, true); + this.operationManager.createSubContext(entryDN, extractAttributes(attributedType, true)); + addToParentAsMember(attributedType); + attributedType.setId(getEntryIdentifier(attributedType)); + + attributedType.setEntryDN(entryDN); + + if (logger.isTraceEnabled()) { + logger.tracef("Type with identifier [%s] successfully added to identity store [%s].", attributedType.getId(), this); + } + } + + @Override + public void update(AttributedType attributedType) { + BasicAttributes updatedAttributes = extractAttributes(attributedType, false); + NamingEnumeration attributes = updatedAttributes.getAll(); + + this.operationManager.modifyAttributes(getBindingDN(attributedType, true), attributes); + + if (logger.isTraceEnabled()) { + logger.tracef("Type with identifier [%s] successfully updated to identity store [%s].", attributedType.getId(), this); + } + } + + @Override + public void remove(AttributedType attributedType) { + LDAPMappingConfiguration mappingConfig = getMappingConfig(attributedType.getClass()); + + this.operationManager.removeEntryById(getBaseDN(attributedType), attributedType.getId(), mappingConfig); + + if (logger.isTraceEnabled()) { + logger.tracef("Type with identifier [%s] successfully removed from identity store [%s].", attributedType.getId(), this); + } + } + + @Override + public List fetchQueryResults(IdentityQuery identityQuery) { + List results = new ArrayList(); + + try { + if (identityQuery.getSorting() != null && !identityQuery.getSorting().isEmpty()) { + throw new ModelException("LDAP Identity Store does not support sorted queries."); + } + + for (Condition condition : identityQuery.getConditions()) { + + if (IdentityType.ID.equals(condition.getParameter())) { + if (EqualCondition.class.isInstance(condition)) { + EqualCondition equalCondition = (EqualCondition) condition; + SearchResult search = this.operationManager + .lookupById(getConfig().getBaseDN(), equalCondition.getValue().toString(), null); + + if (search != null) { + results.add((V) populateAttributedType(search, null)); + } + } + + return results; + } + } + + if (!IdentityType.class.equals(identityQuery.getIdentityType())) { + // the ldap store does not support queries based on root types. Except if based on the identifier. + LDAPMappingConfiguration ldapEntryConfig = getMappingConfig(identityQuery.getIdentityType()); + StringBuilder filter = createIdentityTypeSearchFilter(identityQuery, ldapEntryConfig); + String baseDN = getBaseDN(ldapEntryConfig); + List search; + + if (getConfig().isPagination() && identityQuery.getLimit() > 0) { + search = this.operationManager.searchPaginated(baseDN, filter.toString(), ldapEntryConfig, identityQuery); + } else { + search = this.operationManager.search(baseDN, filter.toString(), ldapEntryConfig); + } + + for (SearchResult result : search) { + if (!result.getNameInNamespace().equals(baseDN)) { + results.add((V) populateAttributedType(result, null)); + } + } + } + } catch (Exception e) { + throw new ModelException("Querying of identity type failed " + identityQuery, e); + } + + return results; + } + + @Override + public int countQueryResults(IdentityQuery identityQuery) { + int limit = identityQuery.getLimit(); + int offset = identityQuery.getOffset(); + + identityQuery.setLimit(0); + identityQuery.setOffset(0); + + int resultCount = identityQuery.getResultList().size(); + + identityQuery.setLimit(limit); + identityQuery.setOffset(offset); + + return resultCount; + } + + public IdentityQueryBuilder createQueryBuilder() { + return new DefaultQueryBuilder(this); + } + + // *************** CREDENTIALS AND USER SPECIFIC STUFF + + @Override + public boolean validatePassword(LDAPUser user, String password) { + String userDN = getEntryDNOfUser(user); + + if (logger.isDebugEnabled()) { + logger.debugf("Using DN [%s] for authentication of user [%s]", userDN, user.getLoginName()); + } + + if (operationManager.authenticate(userDN, password)) { + return true; + } + + return false; + } + + @Override + public void updatePassword(LDAPUser user, String password) { + String userDN = getEntryDNOfUser(user); + + if (logger.isDebugEnabled()) { + logger.debugf("Using DN [%s] for updating LDAP password of user [%s]", userDN, user.getLoginName()); + } + + if (getConfig().isActiveDirectory()) { + updateADPassword(userDN, password); + } else { + ModificationItem[] mods = new ModificationItem[1]; + + try { + BasicAttribute mod0 = new BasicAttribute(LDAPConstants.USER_PASSWORD_ATTRIBUTE, password); + + mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, mod0); + + operationManager.modifyAttribute(userDN, mod0); + } catch (Exception e) { + throw new ModelException("Error updating password.", e); + } + } + } + + + private void updateADPassword(String userDN, String password) { + try { + // Replace the "unicdodePwd" attribute with a new value + // Password must be both Unicode and a quoted string + String newQuotedPassword = "\"" + password + "\""; + byte[] newUnicodePassword = newQuotedPassword.getBytes("UTF-16LE"); + + BasicAttribute unicodePwd = new BasicAttribute("unicodePwd", newUnicodePassword); + + List modItems = new ArrayList(); + modItems.add(new ModificationItem(DirContext.REPLACE_ATTRIBUTE, unicodePwd)); + + // Used in ActiveDirectory to put account into "enabled" state (aka userAccountControl=512, see http://support.microsoft.com/kb/305144/en ) after password update. If value is -1, it's ignored + if (getConfig().isUserAccountControlsAfterPasswordUpdate()) { + BasicAttribute userAccountControl = new BasicAttribute("userAccountControl", "512"); + modItems.add(new ModificationItem(DirContext.REPLACE_ATTRIBUTE, userAccountControl)); + + logger.debugf("Attribute userAccountControls will be switched to 512 after password update of user [%s]", userDN); + } + + operationManager.modifyAttributes(userDN, modItems.toArray(new ModificationItem[] {})); + } catch (Exception e) { + throw new ModelException(e); + } + } + + + private String getEntryDNOfUser(LDAPUser user) { + // First try if user already has entryDN on him + String entryDN = user.getEntryDN(); + if (entryDN != null) { + return entryDN; + } + + // Need to find user in LDAP + String username = user.getLoginName(); + user = getUser(username); + if (user == null) { + throw new ModelException("No LDAP user found with username " + username); + } + + return user.getEntryDN(); + } + + + public LDAPUser getUser(String username) { + + if (isNullOrEmpty(username)) { + return null; + } + + IdentityQueryBuilder queryBuilder = createQueryBuilder(); + List agents = queryBuilder.createIdentityQuery(LDAPUser.class) + .where(queryBuilder.equal(LDAPUser.LOGIN_NAME, username)).getResultList(); + + if (agents.isEmpty()) { + return null; + } else if (agents.size() == 1) { + return agents.get(0); + } else { + throw new ModelDuplicateException("Error - multiple Agent objects found with same login name"); + } + } + + // ************ END CREDENTIALS AND USER SPECIFIC STUFF + + + private String getBaseDN(final LDAPMappingConfiguration ldapEntryConfig) { + String baseDN = getConfig().getBaseDN(); + + if (ldapEntryConfig.getBaseDN() != null) { + baseDN = ldapEntryConfig.getBaseDN(); + } + + return baseDN; + } + + protected StringBuilder createIdentityTypeSearchFilter(final IdentityQuery identityQuery, final LDAPMappingConfiguration ldapEntryConfig) { + StringBuilder filter = new StringBuilder(); + + for (Condition condition : identityQuery.getConditions()) { + QueryParameter queryParameter = condition.getParameter(); + + if (!IdentityType.ID.equals(queryParameter)) { + if (AttributeParameter.class.isInstance(queryParameter)) { + AttributeParameter attributeParameter = (AttributeParameter) queryParameter; + String attributeName = ldapEntryConfig.getMappedProperties().get(attributeParameter.getName()); + + if (attributeName != null) { + if (EqualCondition.class.isInstance(condition)) { + EqualCondition equalCondition = (EqualCondition) condition; + Object parameterValue = equalCondition.getValue(); + + if (Date.class.isInstance(parameterValue)) { + parameterValue = LDAPUtil.formatDate((Date) parameterValue); + } + + filter.append("(").append(attributeName).append(LDAPConstants.EQUAL).append(parameterValue).append(")"); + } else if (LikeCondition.class.isInstance(condition)) { + LikeCondition likeCondition = (LikeCondition) condition; + String parameterValue = (String) likeCondition.getValue(); + + } else if (GreaterThanCondition.class.isInstance(condition)) { + GreaterThanCondition greaterThanCondition = (GreaterThanCondition) condition; + Comparable parameterValue = (Comparable) greaterThanCondition.getValue(); + + if (Date.class.isInstance(parameterValue)) { + parameterValue = LDAPUtil.formatDate((Date) parameterValue); + } + + if (greaterThanCondition.isOrEqual()) { + filter.append("(").append(attributeName).append(">=").append(parameterValue).append(")"); + } else { + filter.append("(").append(attributeName).append(">").append(parameterValue).append(")"); + } + } else if (LessThanCondition.class.isInstance(condition)) { + LessThanCondition lessThanCondition = (LessThanCondition) condition; + Comparable parameterValue = (Comparable) lessThanCondition.getValue(); + + if (Date.class.isInstance(parameterValue)) { + parameterValue = LDAPUtil.formatDate((Date) parameterValue); + } + + if (lessThanCondition.isOrEqual()) { + filter.append("(").append(attributeName).append("<=").append(parameterValue).append(")"); + } else { + filter.append("(").append(attributeName).append("<").append(parameterValue).append(")"); + } + } else if (BetweenCondition.class.isInstance(condition)) { + BetweenCondition betweenCondition = (BetweenCondition) condition; + Comparable x = betweenCondition.getX(); + Comparable y = betweenCondition.getY(); + + if (Date.class.isInstance(x)) { + x = LDAPUtil.formatDate((Date) x); + } + + if (Date.class.isInstance(y)) { + y = LDAPUtil.formatDate((Date) y); + } + + filter.append("(").append(x).append("<=").append(attributeName).append("<=").append(y).append(")"); + } else if (InCondition.class.isInstance(condition)) { + InCondition inCondition = (InCondition) condition; + Object[] valuesToCompare = inCondition.getValue(); + + filter.append("(&("); + + for (int i = 0; i< valuesToCompare.length; i++) { + Object value = valuesToCompare[i]; + + filter.append("(").append(attributeName).append(LDAPConstants.EQUAL).append(value).append(")"); + } + + filter.append("))"); + } else { + throw new ModelException("Unsupported query condition [" + condition + "]."); + } + } + } + } + } + + + filter.insert(0, "(&("); + filter.append(getObjectClassesFilter(ldapEntryConfig)); + filter.append("))"); + + return filter; + } + + private StringBuilder getObjectClassesFilter(final LDAPMappingConfiguration ldapEntryConfig) { + StringBuilder builder = new StringBuilder(); + + if (ldapEntryConfig != null && !ldapEntryConfig.getObjectClasses().isEmpty()) { + for (String objectClass : ldapEntryConfig.getObjectClasses()) { + builder.append("(").append(LDAPConstants.OBJECT_CLASS).append(LDAPConstants.EQUAL).append(objectClass).append(")"); + } + } else { + builder.append("(").append(LDAPConstants.OBJECT_CLASS).append(LDAPConstants.EQUAL).append("*").append(")"); + } + + return builder; + } + + private AttributedType populateAttributedType(SearchResult searchResult, AttributedType attributedType) { + return populateAttributedType(searchResult, attributedType, 0); + } + + private AttributedType populateAttributedType(SearchResult searchResult, AttributedType attributedType, int hierarchyDepthCount) { + try { + String entryDN = searchResult.getNameInNamespace(); + Attributes attributes = searchResult.getAttributes(); + + if (attributedType == null) { + attributedType = Reflections.newInstance(getConfig().getSupportedTypeByBaseDN(entryDN, getEntryObjectClasses(attributes))); + } + + attributedType.setEntryDN(entryDN); + + LDAPMappingConfiguration mappingConfig = getMappingConfig(attributedType.getClass()); + + if (hierarchyDepthCount > mappingConfig.getHierarchySearchDepth()) { + return null; + } + + if (logger.isTraceEnabled()) { + logger.tracef("Populating attributed type [%s] from DN [%s]", attributedType, entryDN); + } + + NamingEnumeration ldapAttributes = attributes.getAll(); + + while (ldapAttributes.hasMore()) { + Attribute ldapAttribute = ldapAttributes.next(); + Object attributeValue; + + try { + attributeValue = ldapAttribute.get(); + } catch (NoSuchElementException nsee) { + continue; + } + + String ldapAttributeName = ldapAttribute.getID(); + + if (ldapAttributeName.toLowerCase().equals(getConfig().getUniqueIdentifierAttributeName().toLowerCase())) { + attributedType.setId(this.operationManager.decodeEntryUUID(attributeValue)); + } else { + String attributeName = findAttributeName(mappingConfig.getMappedProperties(), ldapAttributeName); + + if (attributeName != null) { + // Find if it's java property or attribute + Property property = PropertyQueries + .createQuery(attributedType.getClass()) + .addCriteria(new NamedPropertyCriteria(attributeName)).getFirstResult(); + + if (property != null) { + if (logger.isTraceEnabled()) { + logger.tracef("Populating property [%s] from ldap attribute [%s] with value [%s] from DN [%s].", property.getName(), ldapAttributeName, attributeValue, entryDN); + } + + if (property.getJavaClass().equals(Date.class)) { + property.setValue(attributedType, LDAPUtil.parseDate(attributeValue.toString())); + } else { + property.setValue(attributedType, attributeValue); + } + } else { + if (logger.isTraceEnabled()) { + logger.tracef("Populating attribute [%s] from ldap attribute [%s] with value [%s] from DN [%s].", attributeName, ldapAttributeName, attributeValue, entryDN); + } + + attributedType.setAttribute(new org.keycloak.federation.ldap.idm.model.Attribute(attributeName, (Serializable) attributeValue)); + } + } + } + } + + if (IdentityType.class.isInstance(attributedType)) { + IdentityType identityType = (IdentityType) attributedType; + + String createdTimestamp = attributes.get(LDAPConstants.CREATE_TIMESTAMP).get().toString(); + + identityType.setCreatedDate(LDAPUtil.parseDate(createdTimestamp)); + } + + LDAPMappingConfiguration entryConfig = getMappingConfig(attributedType.getClass()); + + if (mappingConfig.getParentMembershipAttributeName() != null) { + StringBuilder filter = new StringBuilder("(&"); + String entryBaseDN = entryDN.substring(entryDN.indexOf(LDAPConstants.COMMA) + 1); + + filter + .append("(") + .append(getObjectClassesFilter(entryConfig)) + .append(")") + .append("(") + .append(mappingConfig.getParentMembershipAttributeName()) + .append(LDAPConstants.EQUAL).append("") + .append(getBindingDN(attributedType, false)) + .append(LDAPConstants.COMMA) + .append(entryBaseDN) + .append(")"); + + filter.append(")"); + + if (logger.isTraceEnabled()) { + logger.tracef("Searching parent entry for DN [%s] using filter [%s].", entryBaseDN, filter.toString()); + } + + List search = this.operationManager.search(getConfig().getBaseDN(), filter.toString(), entryConfig); + + if (!search.isEmpty()) { + SearchResult next = search.get(0); + + Property parentProperty = PropertyQueries + .createQuery(attributedType.getClass()) + .addCriteria(new TypedPropertyCriteria(attributedType.getClass())).getFirstResult(); + + if (parentProperty != null) { + String parentDN = next.getNameInNamespace(); + String parentBaseDN = parentDN.substring(parentDN.indexOf(",") + 1); + Class baseDNType = getConfig().getSupportedTypeByBaseDN(parentBaseDN, getEntryObjectClasses(attributes)); + + if (parentProperty.getJavaClass().isAssignableFrom(baseDNType)) { + if (logger.isTraceEnabled()) { + logger.tracef("Found parent [%s] for entry for DN [%s].", parentDN, entryDN); + } + + int hierarchyDepthCount1 = ++hierarchyDepthCount; + + parentProperty.setValue(attributedType, populateAttributedType(next, null, hierarchyDepthCount1)); + } + } + } else { + if (logger.isTraceEnabled()) { + logger.tracef("No parent entry found for DN [%s] using filter [%s].", entryDN, filter.toString()); + } + } + } + } catch (Exception e) { + throw new ModelException("Could not populate attribute type " + attributedType + ".", e); + } + + return attributedType; + } + + private String findAttributeName(Map attrMapping, String ldapAttributeName) { + for (Map.Entry currentAttr : attrMapping.entrySet()) { + if (currentAttr.getValue().equalsIgnoreCase(ldapAttributeName)) { + return currentAttr.getKey(); + } + } + + return null; + } + + private List getEntryObjectClasses(final Attributes attributes) throws NamingException { + Attribute objectClassesAttribute = attributes.get(LDAPConstants.OBJECT_CLASS); + List objectClasses = new ArrayList(); + + if (objectClassesAttribute == null) { + return objectClasses; + } + + NamingEnumeration all = objectClassesAttribute.getAll(); + + while (all.hasMore()) { + objectClasses.add(all.next().toString()); + } + + return objectClasses; + } + + protected BasicAttributes extractAttributes(AttributedType attributedType, boolean isCreate) { + BasicAttributes entryAttributes = new BasicAttributes(); + LDAPMappingConfiguration mappingConfig = getMappingConfig(attributedType.getClass()); + Map mappedProperties = mappingConfig.getMappedProperties(); + + for (String propertyName : mappedProperties.keySet()) { + if (!mappingConfig.getReadOnlyAttributes().contains(propertyName) && (isCreate || !mappingConfig.getBindingProperty().getName().equals(propertyName))) { + Property property = PropertyQueries + .createQuery(attributedType.getClass()) + .addCriteria(new NamedPropertyCriteria(propertyName)).getFirstResult(); + + Object propertyValue = null; + if (property != null) { + // Mapped Java property on the object + propertyValue = property.getValue(attributedType); + } else { + // Not mapped property. So fallback to attribute + org.keycloak.federation.ldap.idm.model.Attribute attribute = attributedType.getAttribute(propertyName); + if (attribute != null) { + propertyValue = attribute.getValue(); + } + } + + if (AttributedType.class.isInstance(propertyValue)) { + AttributedType referencedType = (AttributedType) propertyValue; + propertyValue = getBindingDN(referencedType, true); + } else { + if (propertyValue == null || isNullOrEmpty(propertyValue.toString())) { + propertyValue = EMPTY_ATTRIBUTE_VALUE; + } + } + + entryAttributes.put(mappedProperties.get(propertyName), propertyValue); + } + } + + // Don't extract object classes for update + if (isCreate) { + LDAPMappingConfiguration ldapEntryConfig = getMappingConfig(attributedType.getClass()); + + BasicAttribute objectClassAttribute = new BasicAttribute(LDAPConstants.OBJECT_CLASS); + + for (String objectClassValue : ldapEntryConfig.getObjectClasses()) { + objectClassAttribute.add(objectClassValue); + + if (objectClassValue.equals(LDAPConstants.GROUP_OF_NAMES) + || objectClassValue.equals(LDAPConstants.GROUP_OF_ENTRIES) + || objectClassValue.equals(LDAPConstants.GROUP_OF_UNIQUE_NAMES)) { + entryAttributes.put(LDAPConstants.MEMBER, EMPTY_ATTRIBUTE_VALUE); + } + } + + entryAttributes.put(objectClassAttribute); + } + + return entryAttributes; + } + + // TODO: Move class StringUtil from SAML module + public static boolean isNullOrEmpty(String str) { + return str == null || str.isEmpty(); + } + + private LDAPMappingConfiguration getMappingConfig(Class attributedType) { + LDAPMappingConfiguration mappingConfig = getConfig().getMappingConfig(attributedType); + + if (mappingConfig == null) { + throw new ModelException("Not mapped type [" + attributedType + "]."); + } + + return mappingConfig; + } + + public String getBindingDN(AttributedType attributedType, boolean appendBaseDN) { + LDAPMappingConfiguration mappingConfig = getMappingConfig(attributedType.getClass()); + Property idProperty = mappingConfig.getIdProperty(); + + String baseDN; + + if (mappingConfig.getBaseDN() == null || !appendBaseDN) { + baseDN = ""; + } else { + baseDN = LDAPConstants.COMMA + getBaseDN(attributedType); + } + + Property bindingProperty = mappingConfig.getBindingProperty(); + String bindingAttribute; + String dn; + + if (bindingProperty == null) { + bindingAttribute = mappingConfig.getMappedProperties().get(idProperty.getName()); + dn = idProperty.getValue(attributedType); + } else { + bindingAttribute = mappingConfig.getMappedProperties().get(bindingProperty.getName()); + dn = mappingConfig.getBindingProperty().getValue(attributedType); + } + + return bindingAttribute + LDAPConstants.EQUAL + dn + baseDN; + } + + private String getBaseDN(AttributedType attributedType) { + LDAPMappingConfiguration mappingConfig = getMappingConfig(attributedType.getClass()); + String baseDN = mappingConfig.getBaseDN(); + String parentDN = mappingConfig.getParentMapping().get(mappingConfig.getIdProperty().getValue(attributedType)); + + if (parentDN != null) { + baseDN = parentDN; + } else { + Property parentProperty = PropertyQueries + .createQuery(attributedType.getClass()) + .addCriteria(new TypedPropertyCriteria(attributedType.getClass())).getFirstResult(); + + if (parentProperty != null) { + AttributedType parentType = parentProperty.getValue(attributedType); + + if (parentType != null) { + Property parentIdProperty = getMappingConfig(parentType.getClass()).getIdProperty(); + + String parentId = parentIdProperty.getValue(parentType); + + String parentBaseDN = mappingConfig.getParentMapping().get(parentId); + + if (parentBaseDN != null) { + baseDN = parentBaseDN; + } else { + baseDN = getBaseDN(parentType); + } + } + } + } + + if (baseDN == null) { + baseDN = getConfig().getBaseDN(); + } + + return baseDN; + } + + protected void addToParentAsMember(final AttributedType attributedType) { + LDAPMappingConfiguration entryConfig = getMappingConfig(attributedType.getClass()); + + if (entryConfig.getParentMembershipAttributeName() != null) { + Property parentProperty = PropertyQueries + .createQuery(attributedType.getClass()) + .addCriteria(new TypedPropertyCriteria(attributedType.getClass())) + .getFirstResult(); + + if (parentProperty != null) { + AttributedType parentType = parentProperty.getValue(attributedType); + + if (parentType != null) { + Attributes attributes = this.operationManager.getAttributes(parentType.getId(), getBaseDN(parentType), entryConfig); + Attribute attribute = attributes.get(entryConfig.getParentMembershipAttributeName()); + + attribute.add(getBindingDN(attributedType, true)); + + this.operationManager.modifyAttribute(getBindingDN(parentType, true), attribute); + } + } + } + } + + protected String getEntryIdentifier(final AttributedType attributedType) { + try { + // we need this to retrieve the entry's identifier from the ldap server + List search = this.operationManager.search(getBaseDN(attributedType), "(" + getBindingDN(attributedType, false) + ")", getMappingConfig(attributedType.getClass())); + Attribute id = search.get(0).getAttributes().get(getConfig().getUniqueIdentifierAttributeName()); + + if (id == null) { + throw new ModelException("Could not retrieve identifier for entry [" + getBindingDN(attributedType, true) + "]."); + } + + return this.operationManager.decodeEntryUUID(id.get()); + } catch (NamingException ne) { + throw new ModelException("Could not add type [" + attributedType + "].", ne); + } + } +} diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/store/ldap/LDAPIdentityStoreConfiguration.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/store/ldap/LDAPIdentityStoreConfiguration.java new file mode 100644 index 0000000000..0c0a2e178e --- /dev/null +++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/store/ldap/LDAPIdentityStoreConfiguration.java @@ -0,0 +1,188 @@ +package org.keycloak.federation.ldap.idm.store.ldap; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import org.keycloak.federation.ldap.idm.model.AttributedType; +import org.keycloak.models.LDAPConstants; +import org.keycloak.models.ModelException; + +/** + * A configuration for the LDAP store. + * + * @author anil saldhana + * @since Sep 6, 2012 + */ + +public class LDAPIdentityStoreConfiguration { + + private String ldapURL; + private String factoryName = "com.sun.jndi.ldap.LdapCtxFactory"; + private String authType = "simple"; + private String protocol; + private String bindDN; + private String bindCredential; + private boolean activeDirectory; + private Properties connectionProperties; + private boolean pagination; + private String uniqueIdentifierAttributeName; + private boolean userAccountControlsAfterPasswordUpdate; + + private String baseDN; + private Map, LDAPMappingConfiguration> mappingConfig = new HashMap, LDAPMappingConfiguration>(); + + public String getLdapURL() { + return this.ldapURL; + } + + public String getFactoryName() { + return this.factoryName; + } + + public String getAuthType() { + return this.authType; + } + + public String getBaseDN() { + return this.baseDN; + } + + public String getBindDN() { + return this.bindDN; + } + + public String getBindCredential() { + return this.bindCredential; + } + + public boolean isActiveDirectory() { + return this.activeDirectory; + } + + public Properties getConnectionProperties() { + return this.connectionProperties; + } + + public LDAPMappingConfiguration mappingConfig(Class clazz) { + LDAPMappingConfiguration mappingConfig = new LDAPMappingConfiguration(clazz); + this.mappingConfig.put(clazz, mappingConfig); + return mappingConfig; + } + + public Class getSupportedTypeByBaseDN(String entryDN, List objectClasses) { + String entryBaseDN = entryDN.substring(entryDN.indexOf(LDAPConstants.COMMA) + 1); + + for (LDAPMappingConfiguration mappingConfig : this.mappingConfig.values()) { + if (mappingConfig.getBaseDN() != null) { + + if (mappingConfig.getBaseDN().equalsIgnoreCase(entryDN) + || mappingConfig.getParentMapping().values().contains(entryDN)) { + return mappingConfig.getMappedClass(); + } + + if (mappingConfig.getBaseDN().equalsIgnoreCase(entryBaseDN) + || mappingConfig.getParentMapping().values().contains(entryBaseDN)) { + return mappingConfig.getMappedClass(); + } + } + } + + for (LDAPMappingConfiguration mappingConfig : this.mappingConfig.values()) { + for (String objectClass : objectClasses) { + if (mappingConfig.getObjectClasses().contains(objectClass)) { + return mappingConfig.getMappedClass(); + } + } + } + + throw new ModelException("No type found with Base DN [" + entryDN + "] or objectClasses [" + objectClasses + "."); + } + + public LDAPMappingConfiguration getMappingConfig(Class attributedType) { + for (LDAPMappingConfiguration mappingConfig : this.mappingConfig.values()) { + if (attributedType.equals(mappingConfig.getMappedClass())) { + return mappingConfig; + } + } + + return null; + } + + public String getProtocol() { + return protocol; + } + + public String getUniqueIdentifierAttributeName() { + return uniqueIdentifierAttributeName; + } + + public boolean isPagination() { + return pagination; + } + + public boolean isUserAccountControlsAfterPasswordUpdate() { + return userAccountControlsAfterPasswordUpdate; + } + + public LDAPIdentityStoreConfiguration setLdapURL(String ldapURL) { + this.ldapURL = ldapURL; + return this; + } + + public LDAPIdentityStoreConfiguration setFactoryName(String factoryName) { + this.factoryName = factoryName; + return this; + } + + public LDAPIdentityStoreConfiguration setAuthType(String authType) { + this.authType = authType; + return this; + } + + public LDAPIdentityStoreConfiguration setProtocol(String protocol) { + this.protocol = protocol; + return this; + } + + public LDAPIdentityStoreConfiguration setBindDN(String bindDN) { + this.bindDN = bindDN; + return this; + } + + public LDAPIdentityStoreConfiguration setBindCredential(String bindCredential) { + this.bindCredential = bindCredential; + return this; + } + + public LDAPIdentityStoreConfiguration setActiveDirectory(boolean activeDirectory) { + this.activeDirectory = activeDirectory; + return this; + } + + public LDAPIdentityStoreConfiguration setPagination(boolean pagination) { + this.pagination = pagination; + return this; + } + + public LDAPIdentityStoreConfiguration setConnectionProperties(Properties connectionProperties) { + this.connectionProperties = connectionProperties; + return this; + } + + public LDAPIdentityStoreConfiguration setUniqueIdentifierAttributeName(String uniqueIdentifierAttributeName) { + this.uniqueIdentifierAttributeName = uniqueIdentifierAttributeName; + return this; + } + + public LDAPIdentityStoreConfiguration setUserAccountControlsAfterPasswordUpdate(boolean userAccountControlsAfterPasswordUpdate) { + this.userAccountControlsAfterPasswordUpdate = userAccountControlsAfterPasswordUpdate; + return this; + } + + public LDAPIdentityStoreConfiguration setBaseDN(String baseDN) { + this.baseDN = baseDN; + return this; + } +} diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/store/ldap/LDAPMappingConfiguration.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/store/ldap/LDAPMappingConfiguration.java new file mode 100644 index 0000000000..033d93bbf2 --- /dev/null +++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/store/ldap/LDAPMappingConfiguration.java @@ -0,0 +1,231 @@ +package org.keycloak.federation.ldap.idm.store.ldap; + +import java.lang.reflect.AnnotatedElement; +import java.lang.reflect.Member; +import java.lang.reflect.Type; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.keycloak.federation.ldap.idm.model.Attribute; +import org.keycloak.federation.ldap.idm.model.AttributedType; +import org.keycloak.federation.ldap.idm.model.IdentityType; +import org.keycloak.models.ModelException; +import org.keycloak.models.utils.reflection.NamedPropertyCriteria; +import org.keycloak.models.utils.reflection.Property; +import org.keycloak.models.utils.reflection.PropertyQueries; + +/** + * @author pedroigor + */ +public class LDAPMappingConfiguration { + + private final Class mappedClass; + private Set objectClasses; + private String baseDN; + private final Map mappedProperties = new HashMap(); + private Property idProperty; + private Class relatedAttributedType; + private String parentMembershipAttributeName; + private Map parentMapping = new HashMap(); + private final Set readOnlyAttributes = new HashSet(); + private int hierarchySearchDepth; + private Property bindingProperty; + + public LDAPMappingConfiguration(Class mappedClass) { + this.mappedClass = mappedClass; + } + + public Class getMappedClass() { + return this.mappedClass; + } + + public Set getObjectClasses() { + return this.objectClasses; + } + + public String getBaseDN() { + return this.baseDN; + } + + public Map getMappedProperties() { + return this.mappedProperties; + } + + public Property getIdProperty() { + return this.idProperty; + } + + public Property getBindingProperty() { + return this.bindingProperty; + } + + public Class getRelatedAttributedType() { + return this.relatedAttributedType; + } + + public String getParentMembershipAttributeName() { + return this.parentMembershipAttributeName; + } + + public Map getParentMapping() { + return this.parentMapping; + } + + public Set getReadOnlyAttributes() { + return this.readOnlyAttributes; + } + + public int getHierarchySearchDepth() { + return this.hierarchySearchDepth; + } + + private Property getBindingProperty(final String bindingPropertyName) { + Property bindingProperty = PropertyQueries + .createQuery(getMappedClass()) + .addCriteria(new NamedPropertyCriteria(bindingPropertyName)).getFirstResult(); + + // We don't have Java property, so actually delegate to setAttribute/getAttribute + if (bindingProperty == null) { + bindingProperty = new Property() { + + @Override + public String getName() { + return bindingPropertyName; + } + + @Override + public Type getBaseType() { + return null; + } + + @Override + public Class getJavaClass() { + return String.class; + } + + @Override + public AnnotatedElement getAnnotatedElement() { + return null; + } + + @Override + public Member getMember() { + return null; + } + + @Override + public String getValue(Object instance) { + if (!(instance instanceof AttributedType)) { + throw new IllegalStateException("Instance [ " + instance + " ] not an instance of AttributedType"); + } + + AttributedType attributedType = (AttributedType) instance; + Attribute attr = attributedType.getAttribute(bindingPropertyName); + return attr!=null ? attr.getValue() : null; + } + + @Override + public void setValue(Object instance, String value) { + if (!(instance instanceof AttributedType)) { + throw new IllegalStateException("Instance [ " + instance + " ] not an instance of AttributedType"); + } + + AttributedType attributedType = (AttributedType) instance; + attributedType.setAttribute(new Attribute(bindingPropertyName, value)); + } + + @Override + public Class getDeclaringClass() { + return null; + } + + @Override + public boolean isReadOnly() { + return false; + } + + @Override + public void setAccessible() { + + } + + @Override + public boolean isAnnotationPresent(Class annotation) { + return false; + } + }; + } + + return bindingProperty; + } + + public LDAPMappingConfiguration setObjectClasses(Set objectClasses) { + this.objectClasses = objectClasses; + return this; + } + + public LDAPMappingConfiguration setBaseDN(String baseDN) { + this.baseDN = baseDN; + return this; + } + + public LDAPMappingConfiguration addAttributeMapping(String userAttributeName, String ldapAttributeName) { + this.mappedProperties.put(userAttributeName, ldapAttributeName); + return this; + } + + public LDAPMappingConfiguration addReadOnlyAttributeMapping(String userAttributeName, String ldapAttributeName) { + this.mappedProperties.put(userAttributeName, ldapAttributeName); + this.readOnlyAttributes.add(userAttributeName); + return this; + } + + public LDAPMappingConfiguration setIdPropertyName(String idPropertyName) { + + if (idPropertyName != null) { + this.idProperty = PropertyQueries + .createQuery(getMappedClass()) + .addCriteria(new NamedPropertyCriteria(idPropertyName)).getFirstResult(); + } else { + this.idProperty = null; + } + + if (IdentityType.class.isAssignableFrom(mappedClass) && idProperty == null) { + throw new ModelException("Id attribute not mapped to any property of [" + mappedClass + "]."); + } + + // Binding property is idProperty by default + if (this.bindingProperty == null) { + this.bindingProperty = this.idProperty; + } + + return this; + } + + public LDAPMappingConfiguration setRelatedAttributedType(Class relatedAttributedType) { + this.relatedAttributedType = relatedAttributedType; + return this; + } + + public LDAPMappingConfiguration setParentMembershipAttributeName(String parentMembershipAttributeName) { + this.parentMembershipAttributeName = parentMembershipAttributeName; + return this; + } + + public LDAPMappingConfiguration setParentMapping(Map parentMapping) { + this.parentMapping = parentMapping; + return this; + } + + public LDAPMappingConfiguration setHierarchySearchDepth(int hierarchySearchDepth) { + this.hierarchySearchDepth = hierarchySearchDepth; + return this; + } + + public LDAPMappingConfiguration setBindingPropertyName(String bindingPropertyName) { + this.bindingProperty = getBindingProperty(bindingPropertyName); + return this; + } +} diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/store/ldap/LDAPOperationManager.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/store/ldap/LDAPOperationManager.java new file mode 100644 index 0000000000..507d61fc3f --- /dev/null +++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/store/ldap/LDAPOperationManager.java @@ -0,0 +1,606 @@ +package org.keycloak.federation.ldap.idm.store.ldap; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import javax.naming.Binding; +import javax.naming.Context; +import javax.naming.InitialContext; +import javax.naming.NamingEnumeration; +import javax.naming.NamingException; +import javax.naming.directory.Attribute; +import javax.naming.directory.Attributes; +import javax.naming.directory.DirContext; +import javax.naming.directory.ModificationItem; +import javax.naming.directory.SearchControls; +import javax.naming.directory.SearchResult; +import javax.naming.ldap.Control; +import javax.naming.ldap.InitialLdapContext; +import javax.naming.ldap.LdapContext; +import javax.naming.ldap.PagedResultsControl; +import javax.naming.ldap.PagedResultsResponseControl; + +import org.jboss.logging.Logger; +import org.keycloak.federation.ldap.idm.model.IdentityType; +import org.keycloak.federation.ldap.idm.query.IdentityQuery; +import org.keycloak.models.LDAPConstants; +import org.keycloak.models.ModelException; + +import static javax.naming.directory.SearchControls.SUBTREE_SCOPE; + +/** + *

    This class provides a set of operations to manage LDAP trees.

    + * + * @author Anil Saldhana + * @author Pedro Silva + */ +public class LDAPOperationManager { + + private static final Logger logger = Logger.getLogger(LDAPOperationManager.class); + + private final LDAPIdentityStoreConfiguration config; + private final Map connectionProperties; + + public LDAPOperationManager(LDAPIdentityStoreConfiguration config) throws NamingException { + this.config = config; + this.connectionProperties = Collections.unmodifiableMap(createConnectionProperties()); + } + + /** + *

    + * Modifies the given {@link javax.naming.directory.Attribute} instance using the given DN. This method performs a REPLACE_ATTRIBUTE + * operation. + *

    + * + * @param dn + * @param attribute + */ + public void modifyAttribute(String dn, Attribute attribute) { + ModificationItem[] mods = new ModificationItem[]{new ModificationItem(DirContext.REPLACE_ATTRIBUTE, attribute)}; + modifyAttributes(dn, mods); + } + + /** + *

    + * Modifies the given {@link Attribute} instances using the given DN. This method performs a REPLACE_ATTRIBUTE + * operation. + *

    + * + * @param dn + * @param attributes + */ + public void modifyAttributes(String dn, NamingEnumeration attributes) { + try { + List modItems = new ArrayList(); + while (attributes.hasMore()) { + ModificationItem modItem = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, attributes.next()); + modItems.add(modItem); + } + + modifyAttributes(dn, modItems.toArray(new ModificationItem[] {})); + } catch (NamingException ne) { + throw new ModelException("Could not modify attributes on entry from DN [" + dn + "]", ne); + } + + } + + /** + *

    + * Removes the given {@link Attribute} instance using the given DN. This method performs a REMOVE_ATTRIBUTE + * operation. + *

    + * + * @param dn + * @param attribute + */ + public void removeAttribute(String dn, Attribute attribute) { + ModificationItem[] mods = new ModificationItem[]{new ModificationItem(DirContext.REMOVE_ATTRIBUTE, attribute)}; + modifyAttributes(dn, mods); + } + + /** + *

    + * Adds the given {@link Attribute} instance using the given DN. This method performs a ADD_ATTRIBUTE operation. + *

    + * + * @param dn + * @param attribute + */ + public void addAttribute(String dn, Attribute attribute) { + ModificationItem[] mods = new ModificationItem[]{new ModificationItem(DirContext.ADD_ATTRIBUTE, attribute)}; + modifyAttributes(dn, mods); + } + + /** + *

    + * Searches the LDAP tree. + *

    + * + * @param baseDN + * @param id + * + * @return + */ + public void removeEntryById(final String baseDN, final String id, final LDAPMappingConfiguration mappingConfiguration) { + final String filter = getFilterById(baseDN, id); + + try { + final SearchControls cons = getSearchControls(mappingConfiguration); + + execute(new LdapOperation() { + @Override + public SearchResult execute(LdapContext context) throws NamingException { + NamingEnumeration result = context.search(baseDN, filter, cons); + + if (result.hasMore()) { + SearchResult sr = result.next(); + if (logger.isDebugEnabled()) { + logger.debugf("Removing entry [%s] with attributes: [", sr.getNameInNamespace()); + + NamingEnumeration all = sr.getAttributes().getAll(); + + while (all.hasMore()) { + Attribute attribute = all.next(); + + logger.debugf(" %s = %s", attribute.getID(), attribute.get()); + } + + logger.debugf("]"); + } + destroySubcontext(context, sr.getNameInNamespace()); + } + + result.close(); + + return null; + } + }); + } catch (NamingException e) { + throw new ModelException("Could not remove entry from DN [" + baseDN + "] and id [" + id + "]", e); + } + } + + public List search(final String baseDN, final String filter, LDAPMappingConfiguration mappingConfiguration) throws NamingException { + final List result = new ArrayList(); + final SearchControls cons = getSearchControls(mappingConfiguration); + + try { + return execute(new LdapOperation>() { + @Override + public List execute(LdapContext context) throws NamingException { + NamingEnumeration search = context.search(baseDN, filter, cons); + + while (search.hasMoreElements()) { + result.add(search.nextElement()); + } + + search.close(); + + return result; + } + }); + } catch (NamingException e) { + logger.errorf(e, "Could not query server using DN [%s] and filter [%s]", baseDN, filter); + throw e; + } + } + + public List searchPaginated(final String baseDN, final String filter, LDAPMappingConfiguration mappingConfiguration, final IdentityQuery identityQuery) throws NamingException { + final List result = new ArrayList(); + final SearchControls cons = getSearchControls(mappingConfiguration); + + try { + return execute(new LdapOperation>() { + @Override + public List execute(LdapContext context) throws NamingException { + try { + byte[] cookie = (byte[])identityQuery.getPaginationContext(); + PagedResultsControl pagedControls = new PagedResultsControl(identityQuery.getLimit(), cookie, Control.CRITICAL); + context.setRequestControls(new Control[] { pagedControls }); + + NamingEnumeration search = context.search(baseDN, filter, cons); + + while (search.hasMoreElements()) { + result.add(search.nextElement()); + } + + search.close(); + + Control[] responseControls = context.getResponseControls(); + if (responseControls != null) { + for (Control respControl : responseControls) { + if (respControl instanceof PagedResultsResponseControl) { + PagedResultsResponseControl prrc = (PagedResultsResponseControl)respControl; + cookie = prrc.getCookie(); + identityQuery.setPaginationContext(cookie); + } + } + } + + return result; + } catch (IOException ioe) { + logger.errorf(ioe, "Could not query server with paginated query using DN [%s], filter [%s]", baseDN, filter); + throw new NamingException(ioe.getMessage()); + } + } + }); + } catch (NamingException e) { + logger.errorf(e, "Could not query server using DN [%s] and filter [%s]", baseDN, filter); + throw e; + } + } + + private SearchControls getSearchControls(LDAPMappingConfiguration mappingConfiguration) { + final SearchControls cons = new SearchControls(); + + cons.setSearchScope(SUBTREE_SCOPE); + cons.setReturningObjFlag(false); + + List returningAttributes = getReturningAttributes(mappingConfiguration); + + cons.setReturningAttributes(returningAttributes.toArray(new String[returningAttributes.size()])); + return cons; + } + + public String getFilterById(String baseDN, String id) { + String filter = null; + + if (this.config.isActiveDirectory()) { + final String strObjectGUID = ""; + + try { + Attributes attributes = execute(new LdapOperation() { + @Override + public Attributes execute(LdapContext context) throws NamingException { + return context.getAttributes(strObjectGUID); + } + }); + + byte[] objectGUID = (byte[]) attributes.get(LDAPConstants.OBJECT_GUID).get(); + + filter = "(&(objectClass=*)(" + getUniqueIdentifierAttributeName() + LDAPConstants.EQUAL + LDAPUtil.convertObjectGUIToByteString(objectGUID) + "))"; + } catch (NamingException ne) { + return filter; + } + } + + if (filter == null) { + filter = "(&(objectClass=*)(" + getUniqueIdentifierAttributeName() + LDAPConstants.EQUAL + id + "))"; + } + + return filter; + } + + public SearchResult lookupById(final String baseDN, final String id, final LDAPMappingConfiguration mappingConfiguration) { + final String filter = getFilterById(baseDN, id); + + try { + final SearchControls cons = getSearchControls(mappingConfiguration); + + return execute(new LdapOperation() { + @Override + public SearchResult execute(LdapContext context) throws NamingException { + NamingEnumeration search = context.search(baseDN, filter, cons); + + try { + if (search.hasMoreElements()) { + return search.next(); + } + } finally { + if (search != null) { + search.close(); + } + } + + return null; + } + }); + } catch (NamingException e) { + throw new ModelException("Could not query server using DN [" + baseDN + "] and filter [" + filter + "]", e); + } + } + + /** + *

    + * Destroys a subcontext with the given DN from the LDAP tree. + *

    + * + * @param dn + */ + private void destroySubcontext(LdapContext context, final String dn) { + try { + NamingEnumeration enumeration = null; + + try { + enumeration = context.listBindings(dn); + + while (enumeration.hasMore()) { + Binding binding = enumeration.next(); + String name = binding.getNameInNamespace(); + + destroySubcontext(context, name); + } + + context.unbind(dn); + } finally { + try { + enumeration.close(); + } catch (Exception e) { + } + } + } catch (Exception e) { + throw new ModelException("Could not unbind DN [" + dn + "]", e); + } + } + + /** + *

    + * Performs a simple authentication using the given DN and password to bind to the authentication context. + *

    + * + * @param dn + * @param password + * + * @return + */ + public boolean authenticate(String dn, String password) { + InitialContext authCtx = null; + + try { + Hashtable env = new Hashtable(this.connectionProperties); + + env.put(Context.SECURITY_PRINCIPAL, dn); + env.put(Context.SECURITY_CREDENTIALS, password); + + // Never use connection pool to prevent password caching + env.put("com.sun.jndi.ldap.connect.pool", "false"); + + authCtx = new InitialLdapContext(env, null); + + return true; + } catch (Exception e) { + if (logger.isDebugEnabled()) { + logger.debugf(e, "Authentication failed for DN [%s]", dn); + } + + return false; + } finally { + if (authCtx != null) { + try { + authCtx.close(); + } catch (NamingException e) { + + } + } + } + } + + public void modifyAttributes(final String dn, final ModificationItem[] mods) { + try { + if (logger.isDebugEnabled()) { + logger.debugf("Modifying attributes for entry [%s]: [", dn); + + for (ModificationItem item : mods) { + Object values; + + if (item.getAttribute().size() > 0) { + values = item.getAttribute().get(); + } else { + values = "No values"; + } + + logger.debugf(" Op [%s]: %s = %s", item.getModificationOp(), item.getAttribute().getID(), values); + } + + logger.debugf("]"); + } + + execute(new LdapOperation() { + @Override + public Void execute(LdapContext context) throws NamingException { + context.modifyAttributes(dn, mods); + return null; + } + }); + } catch (NamingException e) { + throw new ModelException("Could not modify attribute for DN [" + dn + "]", e); + } + } + + public void createSubContext(final String name, final Attributes attributes) { + try { + if (logger.isDebugEnabled()) { + logger.debugf("Creating entry [%s] with attributes: [", name); + + NamingEnumeration all = attributes.getAll(); + + while (all.hasMore()) { + Attribute attribute = all.next(); + + logger.debugf(" %s = %s", attribute.getID(), attribute.get()); + } + + logger.debugf("]"); + } + + execute(new LdapOperation() { + @Override + public Void execute(LdapContext context) throws NamingException { + DirContext subcontext = context.createSubcontext(name, attributes); + + subcontext.close(); + + return null; + } + }); + } catch (NamingException e) { + throw new ModelException("Error creating subcontext [" + name + "]", e); + } + } + + private String getUniqueIdentifierAttributeName() { + return this.config.getUniqueIdentifierAttributeName(); + } + + private NamingEnumeration createEmptyEnumeration() { + return new NamingEnumeration() { + @Override + public SearchResult next() throws NamingException { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public boolean hasMore() throws NamingException { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public void close() throws NamingException { + //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public boolean hasMoreElements() { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public SearchResult nextElement() { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + }; + } + + public Attributes getAttributes(final String entryUUID, final String baseDN, LDAPMappingConfiguration mappingConfiguration) { + SearchResult search = lookupById(baseDN, entryUUID, mappingConfiguration); + + if (search == null) { + throw new ModelException("Couldn't find item with entryUUID [" + entryUUID + "] and baseDN [" + baseDN + "]"); + } + + return search.getAttributes(); + } + + public String decodeEntryUUID(final Object entryUUID) { + String id; + + if (this.config.isActiveDirectory()) { + id = LDAPUtil.decodeObjectGUID((byte[]) entryUUID); + } else { + id = entryUUID.toString(); + } + + return id; + } + + private LdapContext createLdapContext() throws NamingException { + return new InitialLdapContext(new Hashtable(this.connectionProperties), null); + } + + private Map createConnectionProperties() { + HashMap env = new HashMap(); + + env.put(Context.INITIAL_CONTEXT_FACTORY, this.config.getFactoryName()); + env.put(Context.SECURITY_AUTHENTICATION, this.config.getAuthType()); + + String protocol = this.config.getProtocol(); + + if (protocol != null) { + env.put(Context.SECURITY_PROTOCOL, protocol); + } + + String bindDN = this.config.getBindDN(); + + char[] bindCredential = null; + + if (this.config.getBindCredential() != null) { + bindCredential = this.config.getBindCredential().toCharArray(); + } + + if (bindDN != null) { + env.put(Context.SECURITY_PRINCIPAL, bindDN); + env.put(Context.SECURITY_CREDENTIALS, bindCredential); + } + + String url = this.config.getLdapURL(); + + if (url == null) { + throw new RuntimeException("url"); + } + + env.put(Context.PROVIDER_URL, url); + + // Just dump the additional properties + Properties additionalProperties = this.config.getConnectionProperties(); + + if (additionalProperties != null) { + for (Object key : additionalProperties.keySet()) { + env.put(key.toString(), additionalProperties.getProperty(key.toString())); + } + } + + if (config.isActiveDirectory()) { + env.put("java.naming.ldap.attributes.binary", LDAPConstants.OBJECT_GUID); + } + + if (logger.isDebugEnabled()) { + logger.debugf("Creating LdapContext using properties: [%s]", env); + } + + return env; + } + + private R execute(LdapOperation operation) throws NamingException { + LdapContext context = null; + + try { + context = createLdapContext(); + return operation.execute(context); + } catch (NamingException ne) { + logger.error("Could not create Ldap context or operation execution error.", ne); + throw ne; + } finally { + if (context != null) { + try { + context.close(); + } catch (NamingException ne) { + logger.error("Could not close Ldap context.", ne); + } + } + } + } + + private interface LdapOperation { + R execute(LdapContext context) throws NamingException; + } + + private List getReturningAttributes(final LDAPMappingConfiguration mappingConfiguration) { + List returningAttributes = new ArrayList(); + + if (mappingConfiguration != null) { + returningAttributes.addAll(mappingConfiguration.getMappedProperties().values()); + + returningAttributes.add(mappingConfiguration.getParentMembershipAttributeName()); + +// for (LDAPMappingConfiguration relationshipConfig : this.config.getRelationshipConfigs()) { +// if (relationshipConfig.getRelatedAttributedType().equals(mappingConfiguration.getMappedClass())) { +// returningAttributes.addAll(relationshipConfig.getMappedProperties().values()); +// } +// } + } else { + returningAttributes.add("*"); + } + + returningAttributes.add(getUniqueIdentifierAttributeName()); + returningAttributes.add(LDAPConstants.CREATE_TIMESTAMP); + returningAttributes.add(LDAPConstants.OBJECT_CLASS); + + return returningAttributes; + } +} \ No newline at end of file diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/store/ldap/LDAPUtil.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/store/ldap/LDAPUtil.java new file mode 100644 index 0000000000..f08ff855b2 --- /dev/null +++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/store/ldap/LDAPUtil.java @@ -0,0 +1,158 @@ +package org.keycloak.federation.ldap.idm.store.ldap; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.TimeZone; + +import org.keycloak.models.ModelException; + +/** + *

    Utility class for working with LDAP.

    + * + * @author Pedro Igor + */ +public class LDAPUtil { + + /** + *

    Formats the given date.

    + * + * @param date The Date to format. + * + * @return A String representing the formatted date. + */ + public static final String formatDate(Date date) { + if (date == null) { + throw new IllegalArgumentException("You must provide a date."); + } + + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss'.0Z'"); + + dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + + return dateFormat.format(date); + } + + /** + *

    + * Parses dates/time stamps stored in LDAP. Some possible values: + *

    + *
      + *
    • 20020228150820
    • + *
    • 20030228150820Z
    • + *
    • 20050228150820.12
    • + *
    • 20060711011740.0Z
    • + *
    + * + * @param date The date string to parse from. + * + * @return the Date. + */ + public static final Date parseDate(String date) { + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss"); + + try { + if (date.endsWith("Z")) { + dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + } else { + dateFormat.setTimeZone(TimeZone.getDefault()); + } + + return dateFormat.parse(date); + } catch (Exception e) { + throw new ModelException("Error converting ldap date.", e); + } + } + + + + /** + *

    Creates a byte-based {@link String} representation of a raw byte array representing the value of the + * objectGUID attribute retrieved from Active Directory.

    + * + *

    The returned string is useful to perform queries on AD based on the objectGUID value. Eg.:

    + * + *

    + * String filter = "(&(objectClass=*)(objectGUID" + EQUAL + convertObjectGUIToByteString(objectGUID) + "))"; + *

    + * + * @param objectGUID A raw byte array representing the value of the objectGUID attribute retrieved from + * Active Directory. + * + * @return A byte-based String representation in the form of \[0]\[1]\[2]\[3]\[4]\[5]\[6]\[7]\[8]\[9]\[10]\[11]\[12]\[13]\[14]\[15] + */ + public static String convertObjectGUIToByteString(byte[] objectGUID) { + StringBuilder result = new StringBuilder(); + + for (int i = 0; i < objectGUID.length; i++) { + String transformed = prefixZeros((int) objectGUID[i] & 0xFF); + result.append("\\"); + result.append(transformed); + } + + return result.toString(); + } + + /** + *

    Decode a raw byte array representing the value of the objectGUID attribute retrieved from Active + * Directory.

    + * + *

    The returned string is useful to directly bind an entry. Eg.:

    + * + *

    + * String bindingString = decodeObjectGUID(objectGUID); + *
    + * Attributes attributes = ctx.getAttributes(bindingString); + *

    + * + * @param objectGUID A raw byte array representing the value of the objectGUID attribute retrieved from + * Active Directory. + * + * @return A string representing the decoded value in the form of [3][2][1][0]-[5][4]-[7][6]-[8][9]-[10][11][12][13][14][15]. + */ + public static String decodeObjectGUID(byte[] objectGUID) { + StringBuilder displayStr = new StringBuilder(); + + displayStr.append(convertToDashedString(objectGUID)); + + return displayStr.toString(); + } + + private static String convertToDashedString(byte[] objectGUID) { + StringBuilder displayStr = new StringBuilder(); + + displayStr.append(prefixZeros((int) objectGUID[3] & 0xFF)); + displayStr.append(prefixZeros((int) objectGUID[2] & 0xFF)); + displayStr.append(prefixZeros((int) objectGUID[1] & 0xFF)); + displayStr.append(prefixZeros((int) objectGUID[0] & 0xFF)); + displayStr.append("-"); + displayStr.append(prefixZeros((int) objectGUID[5] & 0xFF)); + displayStr.append(prefixZeros((int) objectGUID[4] & 0xFF)); + displayStr.append("-"); + displayStr.append(prefixZeros((int) objectGUID[7] & 0xFF)); + displayStr.append(prefixZeros((int) objectGUID[6] & 0xFF)); + displayStr.append("-"); + displayStr.append(prefixZeros((int) objectGUID[8] & 0xFF)); + displayStr.append(prefixZeros((int) objectGUID[9] & 0xFF)); + displayStr.append("-"); + displayStr.append(prefixZeros((int) objectGUID[10] & 0xFF)); + displayStr.append(prefixZeros((int) objectGUID[11] & 0xFF)); + displayStr.append(prefixZeros((int) objectGUID[12] & 0xFF)); + displayStr.append(prefixZeros((int) objectGUID[13] & 0xFF)); + displayStr.append(prefixZeros((int) objectGUID[14] & 0xFF)); + displayStr.append(prefixZeros((int) objectGUID[15] & 0xFF)); + + return displayStr.toString(); + } + + private static String prefixZeros(int value) { + if (value <= 0xF) { + StringBuilder sb = new StringBuilder("0"); + sb.append(Integer.toHexString(value)); + return sb.toString(); + } else { + return Integer.toHexString(value); + } + } + + +} diff --git a/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/model/SessionsBean.java b/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/model/SessionsBean.java index 03ba5b3a0e..646b44b4fd 100755 --- a/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/model/SessionsBean.java +++ b/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/model/SessionsBean.java @@ -1,14 +1,11 @@ package org.keycloak.account.freemarker.model; -import org.keycloak.models.ApplicationModel; import org.keycloak.models.ClientModel; import org.keycloak.models.ClientSessionModel; -import org.keycloak.models.OAuthClientModel; import org.keycloak.models.RealmModel; import org.keycloak.models.UserSessionModel; import org.keycloak.util.Time; -import java.util.ArrayList; import java.util.Date; import java.util.HashSet; import java.util.LinkedList; @@ -63,23 +60,14 @@ public class SessionsBean { return Time.toDate(max); } - public Set getApplications() { - Set apps = new HashSet(); + public Set getClients() { + Set clients = new HashSet(); for (ClientSessionModel clientSession : session.getClientSessions()) { ClientModel client = clientSession.getClient(); - if (client instanceof ApplicationModel) apps.add(client.getClientId()); + clients.add(client.getClientId()); } - return apps; + return clients; } - public List getClients() { - List apps = new ArrayList(); - for (ClientSessionModel clientSession : session.getClientSessions()) { - ClientModel client = clientSession.getClient(); - if (client instanceof OAuthClientModel) apps.add(client.getClientId()); - } - return apps; - } - } } diff --git a/forms/common-themes/src/main/resources/theme/base/account/sessions.ftl b/forms/common-themes/src/main/resources/theme/base/account/sessions.ftl index c781c79381..1c0ef1b0e5 100755 --- a/forms/common-themes/src/main/resources/theme/base/account/sessions.ftl +++ b/forms/common-themes/src/main/resources/theme/base/account/sessions.ftl @@ -14,7 +14,6 @@ ${msg("started")} ${msg("lastAccess")} ${msg("expires")} - ${msg("applications")} ${msg("clients")} @@ -26,11 +25,6 @@ ${session.started?datetime} ${session.lastAccess?datetime} ${session.expires?datetime} - - <#list session.applications as app> - ${app}
    - - <#list session.clients as client> ${client}
    diff --git a/forms/common-themes/src/main/resources/theme/base/admin/index.ftl b/forms/common-themes/src/main/resources/theme/base/admin/index.ftl index 161acdad73..20e21b744f 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/index.ftl +++ b/forms/common-themes/src/main/resources/theme/base/admin/index.ftl @@ -30,8 +30,7 @@ - - + diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/app.js b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/app.js index e38c29cf75..f45453c744 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/app.js +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/app.js @@ -212,8 +212,8 @@ module.config([ '$routeProvider', function($routeProvider) { realm : function(RealmLoader) { return RealmLoader(); }, - applications : function(ApplicationListLoader) { - return ApplicationListLoader(); + clients : function(ClientListLoader) { + return ClientListLoader(); }, roles : function(RoleListLoader) { return RoleListLoader(); @@ -311,8 +311,8 @@ module.config([ '$routeProvider', function($routeProvider) { user : function(UserLoader) { return UserLoader(); }, - applications : function(ApplicationListLoader) { - return ApplicationListLoader(); + clients : function(ClientListLoader) { + return ClientListLoader(); } }, controller : 'UserRoleMappingCtrl' @@ -369,8 +369,8 @@ module.config([ '$routeProvider', function($routeProvider) { roles : function(RoleListLoader) { return RoleListLoader(); }, - applications : function(ApplicationListLoader) { - return ApplicationListLoader(); + clients : function(ClientListLoader) { + return ClientListLoader(); } }, controller : 'RoleDetailCtrl' @@ -387,8 +387,8 @@ module.config([ '$routeProvider', function($routeProvider) { roles : function(RoleListLoader) { return RoleListLoader(); }, - applications : function(ApplicationListLoader) { - return ApplicationListLoader(); + clients : function(ClientListLoader) { + return ClientListLoader(); } }, controller : 'RoleDetailCtrl' @@ -406,14 +406,14 @@ module.config([ '$routeProvider', function($routeProvider) { controller : 'RoleListCtrl' }) - .when('/create/role/:realm/applications/:application', { - templateUrl : resourceUrl + '/partials/application-role-detail.html', + .when('/create/role/:realm/clients/:client', { + templateUrl : resourceUrl + '/partials/client-role-detail.html', resolve : { realm : function(RealmLoader) { return RealmLoader(); }, - application : function(ApplicationLoader) { - return ApplicationLoader(); + client : function(ClientLoader) { + return ClientLoader(); }, role : function() { return {}; @@ -421,56 +421,56 @@ module.config([ '$routeProvider', function($routeProvider) { roles : function(RoleListLoader) { return RoleListLoader(); }, - applications : function(ApplicationListLoader) { - return ApplicationListLoader(); + clients : function(ClientListLoader) { + return ClientListLoader(); } }, - controller : 'ApplicationRoleDetailCtrl' + controller : 'ClientRoleDetailCtrl' }) - .when('/realms/:realm/applications/:application/roles/:role', { - templateUrl : resourceUrl + '/partials/application-role-detail.html', + .when('/realms/:realm/clients/:client/roles/:role', { + templateUrl : resourceUrl + '/partials/client-role-detail.html', resolve : { realm : function(RealmLoader) { return RealmLoader(); }, - application : function(ApplicationLoader) { - return ApplicationLoader(); + client : function(ClientLoader) { + return ClientLoader(); }, - role : function(ApplicationRoleLoader) { - return ApplicationRoleLoader(); + role : function(ClientRoleLoader) { + return ClientRoleLoader(); }, roles : function(RoleListLoader) { return RoleListLoader(); }, - applications : function(ApplicationListLoader) { - return ApplicationListLoader(); + clients : function(ClientListLoader) { + return ClientListLoader(); } }, - controller : 'ApplicationRoleDetailCtrl' + controller : 'ClientRoleDetailCtrl' }) - .when('/realms/:realm/applications/:application/mappers', { - templateUrl : resourceUrl + '/partials/application-mappers.html', + .when('/realms/:realm/clients/:client/mappers', { + templateUrl : resourceUrl + '/partials/client-mappers.html', resolve : { realm : function(RealmLoader) { return RealmLoader(); }, - application : function(ApplicationLoader) { - return ApplicationLoader(); + client : function(ClientLoader) { + return ClientLoader(); }, serverInfo : function(ServerInfoLoader) { return ServerInfoLoader(); } }, - controller : 'ApplicationProtocolMapperListCtrl' + controller : 'ClientProtocolMapperListCtrl' }) - .when('/realms/:realm/applications/:application/add-mappers', { - templateUrl : resourceUrl + '/partials/application-mappers-add.html', + .when('/realms/:realm/clients/:client/add-mappers', { + templateUrl : resourceUrl + '/partials/client-mappers-add.html', resolve : { realm : function(RealmLoader) { return RealmLoader(); }, - application : function(ApplicationLoader) { - return ApplicationLoader(); + client : function(ClientLoader) { + return ClientLoader(); }, serverInfo : function(ServerInfoLoader) { return ServerInfoLoader(); @@ -478,26 +478,26 @@ module.config([ '$routeProvider', function($routeProvider) { }, controller : 'AddBuiltinProtocolMapperCtrl' }) - .when('/realms/:realm/applications/:application/mappers/:id', { + .when('/realms/:realm/clients/:client/mappers/:id', { templateUrl : resourceUrl + '/partials/protocol-mapper-detail.html', resolve : { realm : function(RealmLoader) { return RealmLoader(); }, - application : function(ApplicationLoader) { - return ApplicationLoader(); + client : function(ClientLoader) { + return ClientLoader(); }, serverInfo : function(ServerInfoLoader) { return ServerInfoLoader(); }, - mapper : function(ApplicationProtocolMapperLoader) { - return ApplicationProtocolMapperLoader(); + mapper : function(ClientProtocolMapperLoader) { + return ClientProtocolMapperLoader(); } }, - controller : 'ApplicationProtocolMapperCtrl' + controller : 'ClientProtocolMapperCtrl' }) - .when('/create/application/:realm/:application/mappers', { + .when('/create/client/:realm/:client/mappers', { templateUrl : resourceUrl + '/partials/protocol-mapper-detail.html', resolve : { realm : function(RealmLoader) { @@ -506,297 +506,231 @@ module.config([ '$routeProvider', function($routeProvider) { serverInfo : function(ServerInfoLoader) { return ServerInfoLoader(); }, - application : function(ApplicationLoader) { - return ApplicationLoader(); + client : function(ClientLoader) { + return ClientLoader(); } }, - controller : 'ApplicationProtocolMapperCreateCtrl' + controller : 'ClientProtocolMapperCreateCtrl' }) - - .when('/realms/:realm/oauth-clients/:oauth/mappers', { - templateUrl : resourceUrl + '/partials/oauth-client-mappers.html', - resolve : { - realm : function(RealmLoader) { - return RealmLoader(); - }, - oauth : function(OAuthClientLoader) { - return OAuthClientLoader(); - }, - serverInfo : function(ServerInfoLoader) { - return ServerInfoLoader(); - } - }, - controller : 'OAuthClientProtocolMapperListCtrl' - }) - .when('/realms/:realm/oauth-clients/:oauth/add-mappers', { - templateUrl : resourceUrl + '/partials/oauth-client-mappers-add.html', - resolve : { - realm : function(RealmLoader) { - return RealmLoader(); - }, - oauth : function(OAuthClientLoader) { - return OAuthClientLoader(); - }, - serverInfo : function(ServerInfoLoader) { - return ServerInfoLoader(); - } - }, - controller : 'OAuthClientAddBuiltinProtocolMapperCtrl' - }) - .when('/realms/:realm/oauth-clients/:oauth/mappers/:id', { - templateUrl : resourceUrl + '/partials/oauth-client-protocol-mapper-detail.html', - resolve : { - realm : function(RealmLoader) { - return RealmLoader(); - }, - oauth : function(OAuthClientLoader) { - return OAuthClientLoader(); - }, - serverInfo : function(ServerInfoLoader) { - return ServerInfoLoader(); - }, - mapper : function(OAuthClientProtocolMapperLoader) { - return OAuthClientProtocolMapperLoader(); - } - - }, - controller : 'OAuthClientProtocolMapperCtrl' - }) - .when('/create/oauth-client/:realm/:oauth/mappers', { - templateUrl : resourceUrl + '/partials/oauth-client-protocol-mapper-detail.html', - resolve : { - realm : function(RealmLoader) { - return RealmLoader(); - }, - serverInfo : function(ServerInfoLoader) { - return ServerInfoLoader(); - }, - oauth : function(OAuthClientLoader) { - return OAuthClientLoader(); - } - }, - controller : 'OAuthClientProtocolMapperCreateCtrl' - }) - - .when('/realms/:realm/applications/:application/sessions', { - templateUrl : resourceUrl + '/partials/application-sessions.html', + .when('/realms/:realm/clients/:client/sessions', { + templateUrl : resourceUrl + '/partials/client-sessions.html', resolve : { realm : function(RealmLoader) { return RealmLoader(); }, - application : function(ApplicationLoader) { - return ApplicationLoader(); + client : function(ClientLoader) { + return ClientLoader(); }, - sessionCount : function(ApplicationSessionCountLoader) { - return ApplicationSessionCountLoader(); + sessionCount : function(ClientSessionCountLoader) { + return ClientSessionCountLoader(); } }, - controller : 'ApplicationSessionsCtrl' + controller : 'ClientSessionsCtrl' }) - .when('/realms/:realm/applications/:application/credentials', { - templateUrl : resourceUrl + '/partials/application-credentials.html', + .when('/realms/:realm/clients/:client/credentials', { + templateUrl : resourceUrl + '/partials/client-credentials.html', resolve : { realm : function(RealmLoader) { return RealmLoader(); }, - application : function(ApplicationLoader) { - return ApplicationLoader(); + client : function(ClientLoader) { + return ClientLoader(); } }, - controller : 'ApplicationCredentialsCtrl' + controller : 'ClientCredentialsCtrl' }) - .when('/realms/:realm/applications/:application/identity-provider', { - templateUrl : resourceUrl + '/partials/application-identity-provider.html', + .when('/realms/:realm/clients/:client/identity-provider', { + templateUrl : resourceUrl + '/partials/client-identity-provider.html', resolve : { realm : function(RealmLoader) { return RealmLoader(); }, - application : function(ApplicationLoader) { - return ApplicationLoader(); + client : function(ClientLoader) { + return ClientLoader(); } }, - controller : 'ApplicationIdentityProviderCtrl' + controller : 'ClientIdentityProviderCtrl' }) - .when('/realms/:realm/applications/:application/clustering', { - templateUrl : resourceUrl + '/partials/application-clustering.html', + .when('/realms/:realm/clients/:client/clustering', { + templateUrl : resourceUrl + '/partials/client-clustering.html', resolve : { realm : function(RealmLoader) { return RealmLoader(); }, - application : function(ApplicationLoader) { - return ApplicationLoader(); + client : function(ClientLoader) { + return ClientLoader(); } }, - controller : 'ApplicationClusteringCtrl' + controller : 'ClientClusteringCtrl' }) - .when('/register-node/realms/:realm/applications/:application/clustering', { - templateUrl : resourceUrl + '/partials/application-clustering-node.html', + .when('/register-node/realms/:realm/clients/:client/clustering', { + templateUrl : resourceUrl + '/partials/client-clustering-node.html', resolve : { realm : function(RealmLoader) { return RealmLoader(); }, - application : function(ApplicationLoader) { - return ApplicationLoader(); + client : function(ClientLoader) { + return ClientLoader(); } }, - controller : 'ApplicationClusteringNodeCtrl' + controller : 'ClientClusteringNodeCtrl' }) - .when('/realms/:realm/applications/:application/clustering/:node', { - templateUrl : resourceUrl + '/partials/application-clustering-node.html', + .when('/realms/:realm/clients/:client/clustering/:node', { + templateUrl : resourceUrl + '/partials/client-clustering-node.html', resolve : { realm : function(RealmLoader) { return RealmLoader(); }, - application : function(ApplicationLoader) { - return ApplicationLoader(); + client : function(ClientLoader) { + return ClientLoader(); } }, - controller : 'ApplicationClusteringNodeCtrl' + controller : 'ClientClusteringNodeCtrl' }) - .when('/realms/:realm/applications/:application/saml/keys', { - templateUrl : resourceUrl + '/partials/application-saml-keys.html', + .when('/realms/:realm/clients/:client/saml/keys', { + templateUrl : resourceUrl + '/partials/client-saml-keys.html', resolve : { realm : function(RealmLoader) { return RealmLoader(); }, - application : function(ApplicationLoader) { - return ApplicationLoader(); + client : function(ClientLoader) { + return ClientLoader(); } }, - controller : 'ApplicationSamlKeyCtrl' + controller : 'ClientSamlKeyCtrl' }) - .when('/realms/:realm/applications/:application/saml/:keyType/import/:attribute', { - templateUrl : resourceUrl + '/partials/application-saml-key-import.html', + .when('/realms/:realm/clients/:client/saml/:keyType/import/:attribute', { + templateUrl : resourceUrl + '/partials/client-saml-key-import.html', resolve : { realm : function(RealmLoader) { return RealmLoader(); }, - application : function(ApplicationLoader) { - return ApplicationLoader(); + client : function(ClientLoader) { + return ClientLoader(); } }, - controller : 'ApplicationCertificateImportCtrl' + controller : 'ClientCertificateImportCtrl' }) - .when('/realms/:realm/applications/:application/saml/:keyType/export/:attribute', { - templateUrl : resourceUrl + '/partials/application-saml-key-export.html', + .when('/realms/:realm/clients/:client/saml/:keyType/export/:attribute', { + templateUrl : resourceUrl + '/partials/client-saml-key-export.html', resolve : { realm : function(RealmLoader) { return RealmLoader(); }, - application : function(ApplicationLoader) { - return ApplicationLoader(); + client : function(ClientLoader) { + return ClientLoader(); } }, - controller : 'ApplicationCertificateExportCtrl' + controller : 'ClientCertificateExportCtrl' }) - .when('/realms/:realm/applications/:application/roles', { - templateUrl : resourceUrl + '/partials/application-role-list.html', + .when('/realms/:realm/clients/:client/roles', { + templateUrl : resourceUrl + '/partials/client-role-list.html', resolve : { realm : function(RealmLoader) { return RealmLoader(); }, - application : function(ApplicationLoader) { - return ApplicationLoader(); + client : function(ClientLoader) { + return ClientLoader(); }, - roles : function(ApplicationRoleListLoader) { - return ApplicationRoleListLoader(); + roles : function(ClientRoleListLoader) { + return ClientRoleListLoader(); } }, - controller : 'ApplicationRoleListCtrl' + controller : 'ClientRoleListCtrl' }) - .when('/realms/:realm/applications/:application/revocation', { - templateUrl : resourceUrl + '/partials/application-revocation.html', + .when('/realms/:realm/clients/:client/revocation', { + templateUrl : resourceUrl + '/partials/client-revocation.html', resolve : { realm : function(RealmLoader) { return RealmLoader(); }, - application : function(ApplicationLoader) { - return ApplicationLoader(); + client : function(ClientLoader) { + return ClientLoader(); } }, - controller : 'ApplicationRevocationCtrl' + controller : 'ClientRevocationCtrl' }) - .when('/realms/:realm/applications/:application/scope-mappings', { - templateUrl : resourceUrl + '/partials/application-scope-mappings.html', + .when('/realms/:realm/clients/:client/scope-mappings', { + templateUrl : resourceUrl + '/partials/client-scope-mappings.html', resolve : { realm : function(RealmLoader) { return RealmLoader(); }, - application : function(ApplicationLoader) { - return ApplicationLoader(); + client : function(ClientLoader) { + return ClientLoader(); }, - applications : function(ApplicationListLoader) { - return ApplicationListLoader(); + clients : function(ClientListLoader) { + return ClientListLoader(); } }, - controller : 'ApplicationScopeMappingCtrl' + controller : 'ClientScopeMappingCtrl' }) - .when('/realms/:realm/applications/:application/installation', { - templateUrl : resourceUrl + '/partials/application-installation.html', + .when('/realms/:realm/clients/:client/installation', { + templateUrl : resourceUrl + '/partials/client-installation.html', resolve : { realm : function(RealmLoader) { return RealmLoader(); }, - application : function(ApplicationLoader) { - return ApplicationLoader(); + client : function(ClientLoader) { + return ClientLoader(); } }, - controller : 'ApplicationInstallationCtrl' + controller : 'ClientInstallationCtrl' }) - .when('/create/application/:realm', { - templateUrl : resourceUrl + '/partials/application-detail.html', + .when('/create/client/:realm', { + templateUrl : resourceUrl + '/partials/client-detail.html', resolve : { realm : function(RealmLoader) { return RealmLoader(); }, - applications : function(ApplicationListLoader) { - return ApplicationListLoader(); + clients : function(ClientListLoader) { + return ClientListLoader(); }, - application : function() { + client : function() { return {}; }, serverInfo : function(ServerInfoLoader) { return ServerInfoLoader(); } }, - controller : 'ApplicationDetailCtrl' + controller : 'ClientDetailCtrl' }) - .when('/realms/:realm/applications/:application', { - templateUrl : resourceUrl + '/partials/application-detail.html', + .when('/realms/:realm/clients/:client', { + templateUrl : resourceUrl + '/partials/client-detail.html', resolve : { realm : function(RealmLoader) { return RealmLoader(); }, - applications : function(ApplicationListLoader) { - return ApplicationListLoader(); + clients : function(ClientListLoader) { + return ClientListLoader(); }, - application : function(ApplicationLoader) { - return ApplicationLoader(); + client : function(ClientLoader) { + return ClientLoader(); }, serverInfo : function(ServerInfoLoader) { return ServerInfoLoader(); } }, - controller : 'ApplicationDetailCtrl' + controller : 'ClientDetailCtrl' }) - .when('/realms/:realm/applications', { - templateUrl : resourceUrl + '/partials/application-list.html', + .when('/realms/:realm/clients', { + templateUrl : resourceUrl + '/partials/client-list.html', resolve : { realm : function(RealmLoader) { return RealmLoader(); }, - applications : function(ApplicationListLoader) { - return ApplicationListLoader(); + clients : function(ClientListLoader) { + return ClientListLoader(); }, serverInfo : function(ServerInfoLoader) { return ServerInfoLoader(); } }, - controller : 'ApplicationListCtrl' + controller : 'ClientListCtrl' }) - .when('/import/application/:realm', { - templateUrl : resourceUrl + '/partials/application-import.html', + .when('/import/client/:realm', { + templateUrl : resourceUrl + '/partials/client-import.html', resolve : { realm : function(RealmLoader) { return RealmLoader(); @@ -805,129 +739,8 @@ module.config([ '$routeProvider', function($routeProvider) { return ServerInfoLoader(); } }, - controller : 'ApplicationImportCtrl' + controller : 'ClientImportCtrl' }) - - // OAUTH Client - - .when('/realms/:realm/oauth-clients/:oauth/claims', { - templateUrl : resourceUrl + '/partials/oauth-client-claims.html', - resolve : { - realm : function(RealmLoader) { - return RealmLoader(); - }, - oauth : function(OAuthClientLoader) { - return OAuthClientLoader(); - }, - claims : function(OAuthClientClaimsLoader) { - return OAuthClientClaimsLoader(); - } - }, - controller : 'OAuthClientClaimsCtrl' - }) - .when('/realms/:realm/oauth-clients/:oauth/revocation', { - templateUrl : resourceUrl + '/partials/oauth-client-revocation.html', - resolve : { - realm : function(RealmLoader) { - return RealmLoader(); - }, - oauth : function(OAuthClientLoader) { - return OAuthClientLoader(); - } - }, - controller : 'OAuthClientRevocationCtrl' - }) - .when('/realms/:realm/oauth-clients/:oauth/credentials', { - templateUrl : resourceUrl + '/partials/oauth-client-credentials.html', - resolve : { - realm : function(RealmLoader) { - return RealmLoader(); - }, - oauth : function(OAuthClientLoader) { - return OAuthClientLoader(); - } - }, - controller : 'OAuthClientCredentialsCtrl' - }) - .when('/realms/:realm/oauth-clients/:oauth/scope-mappings', { - templateUrl : resourceUrl + '/partials/oauth-client-scope-mappings.html', - resolve : { - realm : function(RealmLoader) { - return RealmLoader(); - }, - oauth : function(OAuthClientLoader) { - return OAuthClientLoader(); - }, - applications : function(ApplicationListLoader) { - return ApplicationListLoader(); - } - }, - controller : 'OAuthClientScopeMappingCtrl' - }) - .when('/realms/:realm/oauth-clients/:oauth/installation', { - templateUrl : resourceUrl + '/partials/oauth-client-installation.html', - resolve : { - realm : function(RealmLoader) { - return RealmLoader(); - }, - oauth : function(OAuthClientLoader) { - return OAuthClientLoader(); - }, - installation : function(OAuthClientInstallationLoader) { - return OAuthClientInstallationLoader(); - } - }, - controller : 'OAuthClientInstallationCtrl' - }) - .when('/create/oauth-client/:realm', { - templateUrl : resourceUrl + '/partials/oauth-client-detail.html', - resolve : { - realm : function(RealmLoader) { - return RealmLoader(); - }, - oauth : function() { - return {}; - } - }, - controller : 'OAuthClientDetailCtrl' - }) - .when('/realms/:realm/oauth-clients/:oauth', { - templateUrl : resourceUrl + '/partials/oauth-client-detail.html', - resolve : { - realm : function(RealmLoader) { - return RealmLoader(); - }, - oauth : function(OAuthClientLoader) { - return OAuthClientLoader(); - } - }, - controller : 'OAuthClientDetailCtrl' - }) - .when('/realms/:realm/oauth-clients/:oauth/identity-provider', { - templateUrl : resourceUrl + '/partials/oauth-client-identity-provider.html', - resolve : { - realm : function(RealmLoader) { - return RealmLoader(); - }, - oauth : function(OAuthClientLoader) { - return OAuthClientLoader(); - } - }, - controller : 'OAuthClientIdentityProviderCtrl' - }) - .when('/realms/:realm/oauth-clients', { - templateUrl : resourceUrl + '/partials/oauth-client-list.html', - resolve : { - realm : function(RealmLoader) { - return RealmLoader(); - }, - oauthClients : function(OAuthClientListLoader) { - return OAuthClientListLoader(); - } - }, - controller : 'OAuthClientListCtrl' - }) - .when('/', { templateUrl : resourceUrl + '/partials/home.html', controller : 'HomeCtrl' @@ -959,8 +772,8 @@ module.config([ '$routeProvider', function($routeProvider) { realm : function(RealmLoader) { return RealmLoader(); }, - stats : function(RealmApplicationSessionStatsLoader) { - return RealmApplicationSessionStatsLoader(); + stats : function(RealmClientSessionStatsLoader) { + return RealmClientSessionStatsLoader(); } }, controller : 'RealmSessionStatsCtrl' @@ -1540,21 +1353,12 @@ module.directive('kcNavigation', function ($compile, Notifications) { } }); -module.directive('kcNavigationApplication', function () { +module.directive('kcNavigationClient', function () { return { scope: true, restrict: 'E', replace: true, - templateUrl: resourceUrl + '/templates/kc-navigation-application.html' - } -}); - -module.directive('kcNavigationOauthClient', function () { - return { - scope: true, - restrict: 'E', - replace: true, - templateUrl: resourceUrl + '/templates/kc-navigation-oauth-client.html' + templateUrl: resourceUrl + '/templates/kc-navigation-client.html' } }); diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/applications.js b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js similarity index 51% rename from forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/applications.js rename to forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js index 307f805dea..2324d4876b 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/applications.js +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js @@ -4,14 +4,10 @@ Array.prototype.remove = function(from, to) { return this.push.apply(this, rest); }; -module.controller('ApplicationRoleListCtrl', function($scope, $location, realm, application, roles) { +module.controller('ClientRoleListCtrl', function($scope, $location, realm, client, roles) { $scope.realm = realm; $scope.roles = roles; - $scope.application = application; - - for (var i = 0; i < roles.length; i++) { - console.log("role.id: " + roles[i].id + " role.name: " + roles[i].name); - } + $scope.client = client; $scope.$watch(function() { return $location.path(); @@ -20,17 +16,17 @@ module.controller('ApplicationRoleListCtrl', function($scope, $location, realm, }); }); -module.controller('ApplicationCredentialsCtrl', function($scope, $location, realm, application, ApplicationCredentials, Notifications) { +module.controller('ClientCredentialsCtrl', function($scope, $location, realm, client, ClientCredentials, Notifications) { $scope.realm = realm; - $scope.application = application; - var secret = ApplicationCredentials.get({ realm : realm.realm, application : application.id }, + $scope.client = client; + var secret = ClientCredentials.get({ realm : realm.realm, client : client.id }, function() { $scope.secret = secret.value; } ); $scope.changePassword = function() { - var secret = ApplicationCredentials.update({ realm : realm.realm, application : application.id }, + var secret = ClientCredentials.update({ realm : realm.realm, client : client.id }, function() { Notifications.success('The secret has been changed.'); $scope.secret = secret.value; @@ -49,107 +45,107 @@ module.controller('ApplicationCredentialsCtrl', function($scope, $location, real }); }); -module.controller('ApplicationIdentityProviderCtrl', function($scope, $location, $route, realm, application, Application, $location, Notifications) { +module.controller('ClientIdentityProviderCtrl', function($scope, $location, $route, realm, client, Client, $location, Notifications) { $scope.realm = realm; - $scope.application = angular.copy(application); + $scope.client = angular.copy(client); var length = 0; - if ($scope.application.identityProviders) { - length = $scope.application.identityProviders.length; + if ($scope.client.identityProviders) { + length = $scope.client.identityProviders.length; - for (i = 0; i < $scope.application.identityProviders.length; i++) { - var applicationProvider = $scope.application.identityProviders[i]; - if (applicationProvider.retrieveToken) { - applicationProvider.retrieveToken = applicationProvider.retrieveToken.toString(); + for (i = 0; i < $scope.client.identityProviders.length; i++) { + var clientProvider = $scope.client.identityProviders[i]; + if (clientProvider.retrieveToken) { + clientProvider.retrieveToken = clientProvider.retrieveToken.toString(); } } } else { - $scope.application.identityProviders = []; + $scope.client.identityProviders = []; } $scope.identityProviders = []; - var providersMissingInApp = []; + var providersMissingInClient = []; for (j = 0; j < realm.identityProviders.length; j++) { var identityProvider = realm.identityProviders[j]; - var applicationProvider = null; + var clientProvider = null; - for (i = 0; i < $scope.application.identityProviders.length; i++) { - applicationProvider = $scope.application.identityProviders[i]; + for (i = 0; i < $scope.client.identityProviders.length; i++) { + clientProvider = $scope.client.identityProviders[i]; - if (applicationProvider) { + if (clientProvider) { - if (applicationProvider.id == identityProvider.id) { + if (clientProvider.id == identityProvider.id) { $scope.identityProviders[i] = {}; $scope.identityProviders[i].identityProvider = identityProvider; - $scope.identityProviders[i].retrieveToken = applicationProvider.retrieveToken; + $scope.identityProviders[i].retrieveToken = clientProvider.retrieveToken; break; } - applicationProvider = null; + clientProvider = null; } } - if (applicationProvider == null) { - providersMissingInApp.push(identityProvider); + if (clientProvider == null) { + providersMissingInClient.push(identityProvider); } } - for (j = 0; j < providersMissingInApp.length; j++) { - var identityProvider = providersMissingInApp[j]; + for (j = 0; j < providersMissingInClient.length; j++) { + var identityProvider = providersMissingInClient[j]; var currentProvider = {}; currentProvider.identityProvider = identityProvider; currentProvider.retrieveToken = "false"; $scope.identityProviders.push(currentProvider); - var currentAppProvider = {}; - currentAppProvider.id = identityProvider.id; - currentAppProvider.retrieveToken = "false"; - $scope.application.identityProviders.push(currentAppProvider); + var currentClientProvider = {}; + currentClientProvider.id = identityProvider.id; + currentClientProvider.retrieveToken = "false"; + $scope.client.identityProviders.push(currentClientProvider); } - var oldCopy = angular.copy($scope.application); + var oldCopy = angular.copy($scope.client); $scope.save = function() { - Application.update({ + Client.update({ realm : realm.realm, - application : application.id - }, $scope.application, function() { + client : client.id + }, $scope.client, function() { $scope.changed = false; $route.reload(); - Notifications.success("Your changes have been saved to the application."); + Notifications.success("Your changes have been saved to the client."); }); }; $scope.reset = function() { - $scope.application = angular.copy(oldCopy); + $scope.client = angular.copy(oldCopy); $scope.changed = false; }; - $scope.$watch('application', function() { - if (!angular.equals($scope.application, oldCopy)) { + $scope.$watch('client', function() { + if (!angular.equals($scope.client, oldCopy)) { $scope.changed = true; } }, true); }); -module.controller('ApplicationSamlKeyCtrl', function($scope, $location, $http, $upload, realm, application, - ApplicationCertificate, ApplicationCertificateGenerate, - ApplicationCertificateDownload, Notifications) { +module.controller('ClientSamlKeyCtrl', function($scope, $location, $http, $upload, realm, client, + ClientCertificate, ClientCertificateGenerate, + ClientCertificateDownload, Notifications) { $scope.realm = realm; - $scope.application = application; + $scope.client = client; - var signingKeyInfo = ApplicationCertificate.get({ realm : realm.realm, application : application.id, attribute: 'saml.signing' }, + var signingKeyInfo = ClientCertificate.get({ realm : realm.realm, client : client.id, attribute: 'saml.signing' }, function() { $scope.signingKeyInfo = signingKeyInfo; } ); $scope.generateSigningKey = function() { - var keyInfo = ApplicationCertificateGenerate.generate({ realm : realm.realm, application : application.id, attribute: 'saml.signing' }, + var keyInfo = ClientCertificateGenerate.generate({ realm : realm.realm, client : client.id, attribute: 'saml.signing' }, function() { Notifications.success('Signing key has been regenerated.'); $scope.signingKeyInfo = keyInfo; @@ -161,21 +157,21 @@ module.controller('ApplicationSamlKeyCtrl', function($scope, $location, $http, $ }; $scope.importSigningKey = function() { - $location.url("/realms/" + realm.realm + "/applications/" + application.id + "/saml/Signing/import/saml.signing"); + $location.url("/realms/" + realm.realm + "/clients/" + client.id + "/saml/Signing/import/saml.signing"); }; $scope.exportSigningKey = function() { - $location.url("/realms/" + realm.realm + "/applications/" + application.id + "/saml/Signing/export/saml.signing"); + $location.url("/realms/" + realm.realm + "/clients/" + client.id + "/saml/Signing/export/saml.signing"); }; - var encryptionKeyInfo = ApplicationCertificate.get({ realm : realm.realm, application : application.id, attribute: 'saml.encryption' }, + var encryptionKeyInfo = ClientCertificate.get({ realm : realm.realm, client : client.id, attribute: 'saml.encryption' }, function() { $scope.encryptionKeyInfo = encryptionKeyInfo; } ); $scope.generateEncryptionKey = function() { - var keyInfo = ApplicationCertificateGenerate.generate({ realm : realm.realm, application : application.id, attribute: 'saml.encryption' }, + var keyInfo = ClientCertificateGenerate.generate({ realm : realm.realm, client : client.id, attribute: 'saml.encryption' }, function() { Notifications.success('Encryption key has been regenerated.'); $scope.encryptionKeyInfo = keyInfo; @@ -187,11 +183,11 @@ module.controller('ApplicationSamlKeyCtrl', function($scope, $location, $http, $ }; $scope.importEncryptionKey = function() { - $location.url("/realms/" + realm.realm + "/applications/" + application.id + "/saml/Encryption/import/saml.encryption"); + $location.url("/realms/" + realm.realm + "/clients/" + client.id + "/saml/Encryption/import/saml.encryption"); }; $scope.exportEncryptionKey = function() { - $location.url("/realms/" + realm.realm + "/applications/" + application.id + "/saml/Encryption/export/saml.encryption"); + $location.url("/realms/" + realm.realm + "/clients/" + client.id + "/saml/Encryption/export/saml.encryption"); }; @@ -202,14 +198,14 @@ module.controller('ApplicationSamlKeyCtrl', function($scope, $location, $http, $ }); }); -module.controller('ApplicationCertificateImportCtrl', function($scope, $location, $http, $upload, realm, application, $routeParams, - ApplicationCertificate, ApplicationCertificateGenerate, - ApplicationCertificateDownload, Notifications) { +module.controller('ClientCertificateImportCtrl', function($scope, $location, $http, $upload, realm, client, $routeParams, + ClientCertificate, ClientCertificateGenerate, + ClientCertificateDownload, Notifications) { var keyType = $routeParams.keyType; var attribute = $routeParams.attribute; $scope.realm = realm; - $scope.application = application; + $scope.client = client; $scope.keyType = keyType; $scope.files = []; @@ -234,7 +230,7 @@ module.controller('ApplicationCertificateImportCtrl', function($scope, $location for (var i = 0; i < $scope.files.length; i++) { var $file = $scope.files[i]; $scope.upload = $upload.upload({ - url: authUrl + '/admin/realms/' + realm.realm + '/applications-by-id/' + application.id + '/certificates/' + attribute + '/upload', + url: authUrl + '/admin/realms/' + realm.realm + '/clients-by-id/' + client.id + '/certificates/' + attribute + '/upload', // method: POST or PUT, // headers: {'headerKey': 'headerValue'}, withCredential: true, data: {keystoreFormat: $scope.uploadKeyFormat, @@ -247,11 +243,9 @@ module.controller('ApplicationCertificateImportCtrl', function($scope, $location //fileFormDataName: myFile, /* customize how data is added to formData. See #40#issuecomment-28612000 for example */ //formDataAppender: function(formData, key, val){} - }).progress(function(evt) { - console.log('percent: ' + parseInt(100.0 * evt.loaded / evt.total)); }).success(function(data, status, headers) { Notifications.success("Keystore uploaded successfully."); - $location.url("/realms/" + realm.realm + "/applications/" + application.id + "/saml/keys"); + $location.url("/realms/" + realm.realm + "/clients/" + client.id + "/saml/keys"); }) .error(function() { Notifications.error("The key store can not be uploaded. Please verify the file."); @@ -268,16 +262,16 @@ module.controller('ApplicationCertificateImportCtrl', function($scope, $location }); }); -module.controller('ApplicationCertificateExportCtrl', function($scope, $location, $http, $upload, realm, application, $routeParams, - ApplicationCertificate, ApplicationCertificateGenerate, - ApplicationCertificateDownload, Notifications) { +module.controller('ClientCertificateExportCtrl', function($scope, $location, $http, $upload, realm, client, $routeParams, + ClientCertificate, ClientCertificateGenerate, + ClientCertificateDownload, Notifications) { var keyType = $routeParams.keyType; var attribute = $routeParams.attribute; $scope.realm = realm; - $scope.application = application; + $scope.client = client; $scope.keyType = keyType; var jks = { - keyAlias: application.name, + keyAlias: client.clientId, realmAlias: realm.realm }; @@ -286,7 +280,7 @@ module.controller('ApplicationCertificateExportCtrl', function($scope, $location "PKCS12" ]; - var keyInfo = ApplicationCertificate.get({ realm : realm.realm, application : application.id, attribute: attribute }, + var keyInfo = ClientCertificate.get({ realm : realm.realm, client : client.id, attribute: attribute }, function() { $scope.keyInfo = keyInfo; } @@ -296,17 +290,17 @@ module.controller('ApplicationCertificateExportCtrl', function($scope, $location $scope.download = function() { $http({ - url: authUrl + '/admin/realms/' + realm.realm + '/applications-by-id/' + application.id + '/certificates/' + attribute + '/download', + url: authUrl + '/admin/realms/' + realm.realm + '/clients-by-id/' + client.id + '/certificates/' + attribute + '/download', method: 'POST', responseType: 'arraybuffer', data: $scope.jks, headers: { 'Content-Type': 'application/json', - 'Accept': 'application/octet-stream' + 'Accept': 'client/octet-stream' } }).success(function(data){ var blob = new Blob([data], { - type: 'application/octet-stream' + type: 'client/octet-stream' }); var ext = ".jks"; if ($scope.jks.format == 'PKCS12') ext = ".p12"; @@ -323,18 +317,18 @@ module.controller('ApplicationCertificateExportCtrl', function($scope, $location }); }); -module.controller('ApplicationSessionsCtrl', function($scope, realm, sessionCount, application, - ApplicationUserSessions) { +module.controller('ClientSessionsCtrl', function($scope, realm, sessionCount, client, + ClientUserSessions) { $scope.realm = realm; $scope.count = sessionCount.count; $scope.sessions = []; - $scope.application = application; + $scope.client = client; $scope.page = 0; $scope.query = { realm : realm.realm, - application: $scope.application.id, + client: $scope.client.id, max : 5, first : 0 } @@ -365,17 +359,17 @@ module.controller('ApplicationSessionsCtrl', function($scope, realm, sessionCoun }; $scope.loadUsers = function() { - ApplicationUserSessions.query($scope.query, function(updated) { + ClientUserSessions.query($scope.query, function(updated) { $scope.sessions = updated; }) }; }); -module.controller('ApplicationRoleDetailCtrl', function($scope, realm, application, role, roles, applications, - Role, ApplicationRole, RoleById, RoleRealmComposites, RoleApplicationComposites, +module.controller('ClientRoleDetailCtrl', function($scope, realm, client, role, roles, clients, + Role, ClientRole, RoleById, RoleRealmComposites, RoleClientComposites, $http, $location, Dialog, Notifications) { $scope.realm = realm; - $scope.application = application; + $scope.client = client; $scope.role = angular.copy(role); $scope.create = !role.name; @@ -383,16 +377,16 @@ module.controller('ApplicationRoleDetailCtrl', function($scope, realm, applicati $scope.save = function() { if ($scope.create) { - ApplicationRole.save({ + ClientRole.save({ realm: realm.realm, - application : application.id + client : client.id }, $scope.role, function (data, headers) { $scope.changed = false; role = angular.copy($scope.role); - ApplicationRole.get({ realm: realm.realm, application : application.id, role: role.name }, function(role) { + ClientRole.get({ realm: realm.realm, client : client.id, role: role.name }, function(role) { var id = role.id; - $location.url("/realms/" + realm.realm + "/applications/" + application.id + "/roles/" + id); + $location.url("/realms/" + realm.realm + "/clients/" + client.id + "/roles/" + id); Notifications.success("The role has been created."); }); }); @@ -405,30 +399,30 @@ module.controller('ApplicationRoleDetailCtrl', function($scope, realm, applicati Dialog.confirmDelete($scope.role.name, 'role', function() { $scope.role.$remove({ realm : realm.realm, - application : application.id, + client : client.id, role : $scope.role.id }, function() { - $location.url("/realms/" + realm.realm + "/applications/" + application.id + "/roles"); + $location.url("/realms/" + realm.realm + "/clients/" + client.id + "/roles"); Notifications.success("The role has been deleted."); }); }); }; $scope.cancel = function () { - $location.url("/realms/" + realm.realm + "/applications/" + application.id + "/roles"); + $location.url("/realms/" + realm.realm + "/clients/" + client.id + "/roles"); }; - roleControl($scope, realm, role, roles, applications, - ApplicationRole, RoleById, RoleRealmComposites, RoleApplicationComposites, + roleControl($scope, realm, role, roles, clients, + ClientRole, RoleById, RoleRealmComposites, RoleClientComposites, $http, $location, Notifications, Dialog); }); -module.controller('ApplicationImportCtrl', function($scope, $location, $upload, realm, serverInfo, Notifications) { +module.controller('ClientImportCtrl', function($scope, $location, $upload, realm, serverInfo, Notifications) { $scope.realm = realm; - $scope.configFormats = serverInfo.applicationImporters; + $scope.configFormats = serverInfo.clientImporters; $scope.configFormat = null; $scope.files = []; @@ -446,7 +440,7 @@ module.controller('ApplicationImportCtrl', function($scope, $location, $upload, for (var i = 0; i < $scope.files.length; i++) { var $file = $scope.files[i]; $scope.upload = $upload.upload({ - url: authUrl + '/admin/realms/' + realm.realm + '/application-importers/' + $scope.configFormat.id + '/upload', + url: authUrl + '/admin/realms/' + realm.realm + '/client-importers/' + $scope.configFormat.id + '/upload', // method: POST or PUT, // headers: {'headerKey': 'headerValue'}, withCredential: true, data: {myObj: ""}, @@ -455,11 +449,9 @@ module.controller('ApplicationImportCtrl', function($scope, $location, $upload, //fileFormDataName: myFile, /* customize how data is added to formData. See #40#issuecomment-28612000 for example */ //formDataAppender: function(formData, key, val){} - }).progress(function(evt) { - console.log('percent: ' + parseInt(100.0 * evt.loaded / evt.total)); }).success(function(data, status, headers) { Notifications.success("Uploaded successfully."); - $location.url("/realms/" + realm.realm + "/applications"); + $location.url("/realms/" + realm.realm + "/clients"); }) .error(function() { Notifications.error("The file can not be uploaded. Please verify the file."); @@ -477,10 +469,10 @@ module.controller('ApplicationImportCtrl', function($scope, $location, $upload, }); -module.controller('ApplicationListCtrl', function($scope, realm, applications, Application, serverInfo, $location) { +module.controller('ClientListCtrl', function($scope, realm, clients, Client, serverInfo, $location) { $scope.realm = realm; - $scope.applications = applications; - $scope.importButton = serverInfo.applicationImporters.length > 0; + $scope.clients = clients; + $scope.importButton = serverInfo.clientImporters.length > 0; $scope.$watch(function() { return $location.path(); }, function() { @@ -488,10 +480,9 @@ module.controller('ApplicationListCtrl', function($scope, realm, applications, A }); }); -module.controller('ApplicationInstallationCtrl', function($scope, realm, application, ApplicationInstallation,ApplicationInstallationJBoss, $http, $routeParams) { - console.log('ApplicationInstallationCtrl'); +module.controller('ClientInstallationCtrl', function($scope, realm, client, ClientInstallation,ClientInstallationJBoss, $http, $routeParams) { $scope.realm = realm; - $scope.application = application; + $scope.client = client; $scope.installation = null; $scope.download = null; $scope.configFormat = null; @@ -503,14 +494,14 @@ module.controller('ApplicationInstallationCtrl', function($scope, realm, applica $scope.changeFormat = function() { if ($scope.configFormat == "keycloak.json") { - var url = ApplicationInstallation.url({ realm: $routeParams.realm, application: $routeParams.application }); + var url = ClientInstallation.url({ realm: $routeParams.realm, client: $routeParams.client }); $http.get(url).success(function(data) { var tmp = angular.fromJson(data); $scope.installation = angular.toJson(tmp, true); $scope.type = 'application/json'; }) } else if ($scope.configFormat == "Wildfly/JBoss Subsystem XML") { - var url = ApplicationInstallationJBoss.url({ realm: $routeParams.realm, application: $routeParams.application }); + var url = ClientInstallationJBoss.url({ realm: $routeParams.realm, client: $routeParams.client }); $http.get(url).success(function(data) { $scope.installation = data; $scope.type = 'text/xml'; @@ -523,9 +514,7 @@ module.controller('ApplicationInstallationCtrl', function($scope, realm, applica } }); -module.controller('ApplicationDetailCtrl', function($scope, realm, application, serverInfo, Application, $location, Dialog, Notifications) { - console.log('ApplicationDetailCtrl'); - +module.controller('ClientDetailCtrl', function($scope, realm, client, serverInfo, Client, $location, Dialog, Notifications) { $scope.accessTypes = [ "confidential", "public", @@ -548,7 +537,7 @@ module.controller('ApplicationDetailCtrl', function($scope, realm, application, ]; $scope.realm = realm; - $scope.create = !application.name; + $scope.create = !client.clientId; $scope.samlAuthnStatement = false; $scope.samlMultiValuedRoles = false; $scope.samlServerSignature = false; @@ -558,43 +547,43 @@ module.controller('ApplicationDetailCtrl', function($scope, realm, application, $scope.samlForcePostBinding = false; $scope.samlForceNameIdFormat = false; if (!$scope.create) { - if (!application.attributes) { - application.attributes = {}; + if (!client.attributes) { + client.attributes = {}; } - $scope.application= angular.copy(application); + $scope.client= angular.copy(client); $scope.accessType = $scope.accessTypes[0]; - if (application.bearerOnly) { + if (client.bearerOnly) { $scope.accessType = $scope.accessTypes[2]; - } else if (application.publicClient) { + } else if (client.publicClient) { $scope.accessType = $scope.accessTypes[1]; } - if (application.protocol) { - $scope.protocol = $scope.protocols[$scope.protocols.indexOf(application.protocol)]; + if (client.protocol) { + $scope.protocol = $scope.protocols[$scope.protocols.indexOf(client.protocol)]; } else { $scope.protocol = $scope.protocols[0]; } - if (application.attributes['saml.signature.algorithm'] == 'RSA_SHA1') { + if (client.attributes['saml.signature.algorithm'] == 'RSA_SHA1') { $scope.signatureAlgorithm = $scope.signatureAlgorithms[0]; - } else if (application.attributes['saml.signature.algorithm'] == 'RSA_SHA256') { + } else if (client.attributes['saml.signature.algorithm'] == 'RSA_SHA256') { $scope.signatureAlgorithm = $scope.signatureAlgorithms[1]; - } else if (application.attributes['saml.signature.algorithm'] == 'RSA_SHA512') { + } else if (client.attributes['saml.signature.algorithm'] == 'RSA_SHA512') { $scope.signatureAlgorithm = $scope.signatureAlgorithms[2]; - } else if (application.attributes['saml.signature.algorithm'] == 'DSA_SHA1') { + } else if (client.attributes['saml.signature.algorithm'] == 'DSA_SHA1') { $scope.signatureAlgorithm = $scope.signatureAlgorithms[3]; } - if (application.attributes['saml_name_id_format'] == 'unspecified') { + if (client.attributes['saml_name_id_format'] == 'unspecified') { $scope.nameIdFormat = $scope.nameIdFormats[0]; - } else if (application.attributes['saml_name_id_format'] == 'email') { + } else if (client.attributes['saml_name_id_format'] == 'email') { $scope.nameIdFormat = $scope.nameIdFormats[1]; - } else if (application.attributes['saml_name_id_format'] == 'transient') { + } else if (client.attributes['saml_name_id_format'] == 'transient') { $scope.nameIdFormat = $scope.nameIdFormats[2]; - } else if (application.attributes['saml_name_id_format'] == 'persistent') { + } else if (client.attributes['saml_name_id_format'] == 'persistent') { $scope.nameIdFormat = $scope.nameIdFormats[3]; } } else { - $scope.application = { enabled: true, attributes: {}}; - $scope.application.redirectUris = []; + $scope.client = { enabled: true, attributes: {}}; + $scope.client.redirectUris = []; $scope.accessType = $scope.accessTypes[0]; $scope.protocol = $scope.protocols[0]; $scope.signatureAlgorithm = $scope.signatureAlgorithms[1]; @@ -603,58 +592,58 @@ module.controller('ApplicationDetailCtrl', function($scope, realm, application, $scope.samlForceNameIdFormat = false; } - if ($scope.application.attributes["saml.server.signature"]) { - if ($scope.application.attributes["saml.server.signature"] == "true") { + if ($scope.client.attributes["saml.server.signature"]) { + if ($scope.client.attributes["saml.server.signature"] == "true") { $scope.samlServerSignature = true; } else { $scope.samlServerSignature = false; } } - if ($scope.application.attributes["saml.assertion.signature"]) { - if ($scope.application.attributes["saml.assertion.signature"] == "true") { + if ($scope.client.attributes["saml.assertion.signature"]) { + if ($scope.client.attributes["saml.assertion.signature"] == "true") { $scope.samlAssertionSignature = true; } else { $scope.samlAssertionSignature = false; } } - if ($scope.application.attributes["saml.client.signature"]) { - if ($scope.application.attributes["saml.client.signature"] == "true") { + if ($scope.client.attributes["saml.client.signature"]) { + if ($scope.client.attributes["saml.client.signature"] == "true") { $scope.samlClientSignature = true; } else { $scope.samlClientSignature = false; } } - if ($scope.application.attributes["saml.encrypt"]) { - if ($scope.application.attributes["saml.encrypt"] == "true") { + if ($scope.client.attributes["saml.encrypt"]) { + if ($scope.client.attributes["saml.encrypt"] == "true") { $scope.samlEncrypt = true; } else { $scope.samlEncrypt = false; } } - if ($scope.application.attributes["saml.authnstatement"]) { - if ($scope.application.attributes["saml.authnstatement"] == "true") { + if ($scope.client.attributes["saml.authnstatement"]) { + if ($scope.client.attributes["saml.authnstatement"] == "true") { $scope.samlAuthnStatement = true; } else { $scope.samlAuthnStatement = false; } } - if ($scope.application.attributes["saml_force_name_id_format"]) { - if ($scope.application.attributes["saml_force_name_id_format"] == "true") { + if ($scope.client.attributes["saml_force_name_id_format"]) { + if ($scope.client.attributes["saml_force_name_id_format"] == "true") { $scope.samlForceNameIdFormat = true; } else { $scope.samlForceNameIdFormat = false; } } - if ($scope.application.attributes["saml.multivalued.roles"]) { - if ($scope.application.attributes["saml.multivalued.roles"] == "true") { + if ($scope.client.attributes["saml.multivalued.roles"]) { + if ($scope.client.attributes["saml.multivalued.roles"] == "true") { $scope.samlMultiValuedRoles = true; } else { $scope.samlMultiValuedRoles = false; } } - if ($scope.application.attributes["saml.force.post.binding"]) { - if ($scope.application.attributes["saml.force.post.binding"] == "true") { + if ($scope.client.attributes["saml.force.post.binding"]) { + if ($scope.client.attributes["saml.force.post.binding"] == "true") { $scope.samlForcePostBinding = true; } else { $scope.samlForcePostBinding = false; @@ -667,31 +656,31 @@ module.controller('ApplicationDetailCtrl', function($scope, realm, application, $scope.changeAccessType = function() { if ($scope.accessType == "confidential") { - $scope.application.bearerOnly = false; - $scope.application.publicClient = false; + $scope.client.bearerOnly = false; + $scope.client.publicClient = false; } else if ($scope.accessType == "public") { - $scope.application.bearerOnly = false; - $scope.application.publicClient = true; + $scope.client.bearerOnly = false; + $scope.client.publicClient = true; } else if ($scope.accessType == "bearer-only") { - $scope.application.bearerOnly = true; - $scope.application.publicClient = false; + $scope.client.bearerOnly = true; + $scope.client.publicClient = false; } }; $scope.changeProtocol = function() { if ($scope.protocol == "openid-connect") { - $scope.application.protocol = "openid-connect"; + $scope.client.protocol = "openid-connect"; } else if ($scope.accessType == "saml") { - $scope.application.protocol = "saml"; + $scope.client.protocol = "saml"; } }; $scope.changeAlgorithm = function() { - $scope.application.attributes['saml.signature.algorithm'] = $scope.signatureAlgorithm; + $scope.client.attributes['saml.signature.algorithm'] = $scope.signatureAlgorithm; }; $scope.changeNameIdFormat = function() { - $scope.application.attributes['saml_name_id_format'] = $scope.nameIdFormat; + $scope.client.attributes['saml_name_id_format'] = $scope.nameIdFormat; }; $scope.$watch(function() { @@ -700,125 +689,125 @@ module.controller('ApplicationDetailCtrl', function($scope, realm, application, $scope.path = $location.path().substring(1).split("/"); }); - $scope.$watch('application', function() { - if (!angular.equals($scope.application, application)) { + $scope.$watch('client', function() { + if (!angular.equals($scope.client, client)) { $scope.changed = true; } }, true); $scope.deleteWebOrigin = function(index) { - $scope.application.webOrigins.splice(index, 1); + $scope.client.webOrigins.splice(index, 1); } $scope.addWebOrigin = function() { - $scope.application.webOrigins.push($scope.newWebOrigin); + $scope.client.webOrigins.push($scope.newWebOrigin); $scope.newWebOrigin = ""; } $scope.deleteRedirectUri = function(index) { - $scope.application.redirectUris.splice(index, 1); + $scope.client.redirectUris.splice(index, 1); } $scope.addRedirectUri = function() { - $scope.application.redirectUris.push($scope.newRedirectUri); + $scope.client.redirectUris.push($scope.newRedirectUri); $scope.newRedirectUri = ""; } $scope.save = function() { if ($scope.samlServerSignature == true) { - $scope.application.attributes["saml.server.signature"] = "true"; + $scope.client.attributes["saml.server.signature"] = "true"; } else { - $scope.application.attributes["saml.server.signature"] = "false"; + $scope.client.attributes["saml.server.signature"] = "false"; } if ($scope.samlAssertionSignature == true) { - $scope.application.attributes["saml.assertion.signature"] = "true"; + $scope.client.attributes["saml.assertion.signature"] = "true"; } else { - $scope.application.attributes["saml.assertion.signature"] = "false"; + $scope.client.attributes["saml.assertion.signature"] = "false"; } if ($scope.samlClientSignature == true) { - $scope.application.attributes["saml.client.signature"] = "true"; + $scope.client.attributes["saml.client.signature"] = "true"; } else { - $scope.application.attributes["saml.client.signature"] = "false"; + $scope.client.attributes["saml.client.signature"] = "false"; } if ($scope.samlEncrypt == true) { - $scope.application.attributes["saml.encrypt"] = "true"; + $scope.client.attributes["saml.encrypt"] = "true"; } else { - $scope.application.attributes["saml.encrypt"] = "false"; + $scope.client.attributes["saml.encrypt"] = "false"; } if ($scope.samlAuthnStatement == true) { - $scope.application.attributes["saml.authnstatement"] = "true"; + $scope.client.attributes["saml.authnstatement"] = "true"; } else { - $scope.application.attributes["saml.authnstatement"] = "false"; + $scope.client.attributes["saml.authnstatement"] = "false"; } if ($scope.samlForceNameIdFormat == true) { - $scope.application.attributes["saml_force_name_id_format"] = "true"; + $scope.client.attributes["saml_force_name_id_format"] = "true"; } else { - $scope.application.attributes["saml_force_name_id_format"] = "false"; + $scope.client.attributes["saml_force_name_id_format"] = "false"; } if ($scope.samlMultiValuedRoles == true) { - $scope.application.attributes["saml.multivalued.roles"] = "true"; + $scope.client.attributes["saml.multivalued.roles"] = "true"; } else { - $scope.application.attributes["saml.multivalued.roles"] = "false"; + $scope.client.attributes["saml.multivalued.roles"] = "false"; } if ($scope.samlForcePostBinding == true) { - $scope.application.attributes["saml.force.post.binding"] = "true"; + $scope.client.attributes["saml.force.post.binding"] = "true"; } else { - $scope.application.attributes["saml.force.post.binding"] = "false"; + $scope.client.attributes["saml.force.post.binding"] = "false"; } - $scope.application.protocol = $scope.protocol; - $scope.application.attributes['saml.signature.algorithm'] = $scope.signatureAlgorithm; - $scope.application.attributes['saml_name_id_format'] = $scope.nameIdFormat; + $scope.client.protocol = $scope.protocol; + $scope.client.attributes['saml.signature.algorithm'] = $scope.signatureAlgorithm; + $scope.client.attributes['saml_name_id_format'] = $scope.nameIdFormat; - if ($scope.application.protocol != 'saml' && !$scope.application.bearerOnly && (!$scope.application.redirectUris || $scope.application.redirectUris.length == 0)) { + if ($scope.client.protocol != 'saml' && !$scope.client.bearerOnly && (!$scope.client.redirectUris || $scope.client.redirectUris.length == 0)) { Notifications.error("You must specify at least one redirect uri"); } else { if ($scope.create) { - Application.save({ + Client.save({ realm: realm.realm, - application: '' - }, $scope.application, function (data, headers) { + client: '' + }, $scope.client, function (data, headers) { $scope.changed = false; var l = headers().location; var id = l.substring(l.lastIndexOf("/") + 1); - $location.url("/realms/" + realm.realm + "/applications/" + id); - Notifications.success("The application has been created."); + $location.url("/realms/" + realm.realm + "/clients/" + id); + Notifications.success("The client has been created."); }); } else { - Application.update({ + Client.update({ realm : realm.realm, - application : application.id - }, $scope.application, function() { + client : client.id + }, $scope.client, function() { $scope.changed = false; - application = angular.copy($scope.application); - $location.url("/realms/" + realm.realm + "/applications/" + application.id); - Notifications.success("Your changes have been saved to the application."); + client = angular.copy($scope.client); + $location.url("/realms/" + realm.realm + "/clients/" + client.id); + Notifications.success("Your changes have been saved to the client."); }); } } }; $scope.reset = function() { - $scope.application = angular.copy(application); + $scope.client = angular.copy(client); $scope.changed = false; }; $scope.cancel = function() { - $location.url("/realms/" + realm.realm + "/applications"); + $location.url("/realms/" + realm.realm + "/clients"); }; $scope.remove = function() { - Dialog.confirmDelete($scope.application.name, 'application', function() { - $scope.application.$remove({ + Dialog.confirmDelete($scope.client.clientId, 'client', function() { + $scope.client.$remove({ realm : realm.realm, - application : $scope.application.id + client : $scope.client.id }, function() { - $location.url("/realms/" + realm.realm + "/applications"); - Notifications.success("The application has been deleted."); + $location.url("/realms/" + realm.realm + "/clients"); + Notifications.success("The client has been deleted."); }); }); }; @@ -826,33 +815,32 @@ module.controller('ApplicationDetailCtrl', function($scope, realm, application, }); -module.controller('ApplicationScopeMappingCtrl', function($scope, $http, realm, application, applications, Notifications, - Application, - ApplicationRealmScopeMapping, ApplicationApplicationScopeMapping, ApplicationRole, - ApplicationAvailableRealmScopeMapping, ApplicationAvailableApplicationScopeMapping, - ApplicationCompositeRealmScopeMapping, ApplicationCompositeApplicationScopeMapping) { +module.controller('ClientScopeMappingCtrl', function($scope, $http, realm, client, clients, Notifications, + Client, + ClientRealmScopeMapping, ClientClientScopeMapping, ClientRole, + ClientAvailableRealmScopeMapping, ClientAvailableClientScopeMapping, + ClientCompositeRealmScopeMapping, ClientCompositeClientScopeMapping) { $scope.realm = realm; - $scope.application = angular.copy(application); + $scope.client = angular.copy(client); $scope.selectedRealmRoles = []; $scope.selectedRealmMappings = []; $scope.realmMappings = []; - $scope.applications = applications; - $scope.applicationRoles = []; - $scope.applicationComposite = []; - $scope.selectedApplicationRoles = []; - $scope.selectedApplicationMappings = []; - $scope.applicationMappings = []; + $scope.clients = clients; + $scope.clientRoles = []; + $scope.clientComposite = []; + $scope.selectedClientRoles = []; + $scope.selectedClientMappings = []; + $scope.clientMappings = []; $scope.dummymodel = []; $scope.changeFullScopeAllowed = function() { - console.log('change full scope'); - Application.update({ + Client.update({ realm : realm.realm, - application : application.id - }, $scope.application, function() { + client : client.id + }, $scope.client, function() { $scope.changed = false; - application = angular.copy($scope.application); + client = angular.copy($scope.client); updateRealmRoles(); Notifications.success("Scope mappings updated."); }); @@ -861,30 +849,29 @@ module.controller('ApplicationScopeMappingCtrl', function($scope, $http, realm, function updateRealmRoles() { - $scope.realmRoles = ApplicationAvailableRealmScopeMapping.query({realm : realm.realm, application : application.id}); - $scope.realmMappings = ApplicationRealmScopeMapping.query({realm : realm.realm, application : application.id}); - $scope.realmComposite = ApplicationCompositeRealmScopeMapping.query({realm : realm.realm, application : application.id}); + $scope.realmRoles = ClientAvailableRealmScopeMapping.query({realm : realm.realm, client : client.id}); + $scope.realmMappings = ClientRealmScopeMapping.query({realm : realm.realm, client : client.id}); + $scope.realmComposite = ClientCompositeRealmScopeMapping.query({realm : realm.realm, client : client.id}); } - function updateAppRoles() { - if ($scope.targetApp) { - console.debug($scope.targetApp.name); - $scope.applicationRoles = ApplicationAvailableApplicationScopeMapping.query({realm : realm.realm, application : application.id, targetApp : $scope.targetApp.id}); - $scope.applicationMappings = ApplicationApplicationScopeMapping.query({realm : realm.realm, application : application.id, targetApp : $scope.targetApp.id}); - $scope.applicationComposite = ApplicationCompositeApplicationScopeMapping.query({realm : realm.realm, application : application.id, targetApp : $scope.targetApp.id}); + function updateClientRoles() { + if ($scope.targetClient) { + $scope.clientRoles = ClientAvailableClientScopeMapping.query({realm : realm.realm, client : client.id, targetClient : $scope.targetClient.id}); + $scope.clientMappings = ClientClientScopeMapping.query({realm : realm.realm, client : client.id, targetClient : $scope.targetClient.id}); + $scope.clientComposite = ClientCompositeClientScopeMapping.query({realm : realm.realm, client : client.id, targetClient : $scope.targetClient.id}); } else { - $scope.applicationRoles = null; - $scope.applicationMappings = null; - $scope.applicationComposite = null; + $scope.clientRoles = null; + $scope.clientMappings = null; + $scope.clientComposite = null; } } - $scope.changeApplication = function() { - updateAppRoles(); + $scope.changeClient = function() { + updateClientRoles(); }; $scope.addRealmRole = function() { - $http.post(authUrl + '/admin/realms/' + realm.realm + '/applications-by-id/' + application.id + '/scope-mappings/realm', + $http.post(authUrl + '/admin/realms/' + realm.realm + '/clients-by-id/' + client.id + '/scope-mappings/realm', $scope.selectedRealmRoles).success(function() { updateRealmRoles(); Notifications.success("Scope mappings updated."); @@ -892,25 +879,25 @@ module.controller('ApplicationScopeMappingCtrl', function($scope, $http, realm, }; $scope.deleteRealmRole = function() { - $http.delete(authUrl + '/admin/realms/' + realm.realm + '/applications-by-id/' + application.id + '/scope-mappings/realm', + $http.delete(authUrl + '/admin/realms/' + realm.realm + '/clients-by-id/' + client.id + '/scope-mappings/realm', {data : $scope.selectedRealmMappings, headers : {"content-type" : "application/json"}}).success(function () { updateRealmRoles(); Notifications.success("Scope mappings updated."); }); }; - $scope.addApplicationRole = function() { - $http.post(authUrl + '/admin/realms/' + realm.realm + '/applications-by-id/' + application.id + '/scope-mappings/applications-by-id/' + $scope.targetApp.id, - $scope.selectedApplicationRoles).success(function () { - updateAppRoles(); + $scope.addClientRole = function() { + $http.post(authUrl + '/admin/realms/' + realm.realm + '/clients-by-id/' + client.id + '/scope-mappings/clients-by-id/' + $scope.targetClient.id, + $scope.selectedClientRoles).success(function () { + updateClientRoles(); Notifications.success("Scope mappings updated."); }); }; - $scope.deleteApplicationRole = function() { - $http.delete(authUrl + '/admin/realms/' + realm.realm + '/applications-by-id/' + application.id + '/scope-mappings/applications-by-id/' + $scope.targetApp.id, - {data : $scope.selectedApplicationMappings, headers : {"content-type" : "application/json"}}).success(function () { - updateAppRoles(); + $scope.deleteClientRole = function() { + $http.delete(authUrl + '/admin/realms/' + realm.realm + '/clients-by-id/' + client.id + '/scope-mappings/clients-by-id/' + $scope.targetClient.id, + {data : $scope.selectedClientMappings, headers : {"content-type" : "application/json"}}).success(function () { + updateClientRoles(); Notifications.success("Scope mappings updated."); }); }; @@ -918,45 +905,45 @@ module.controller('ApplicationScopeMappingCtrl', function($scope, $http, realm, updateRealmRoles(); }); -module.controller('ApplicationRevocationCtrl', function($scope, realm, application, Application, ApplicationPushRevocation, $location, Dialog, Notifications) { +module.controller('ClientRevocationCtrl', function($scope, realm, client, Client, ClientPushRevocation, $location, Dialog, Notifications) { $scope.realm = realm; - $scope.application = application; + $scope.client = client; var setNotBefore = function() { - if ($scope.application.notBefore == 0) { + if ($scope.client.notBefore == 0) { $scope.notBefore = "None"; } else { - $scope.notBefore = new Date($scope.application.notBefore * 1000); + $scope.notBefore = new Date($scope.client.notBefore * 1000); } }; setNotBefore(); var refresh = function() { - Application.get({ realm : realm.realm, application: $scope.application.id }, function(updated) { - $scope.application = updated; + Client.get({ realm : realm.realm, client: $scope.client.id }, function(updated) { + $scope.client = updated; setNotBefore(); }) }; $scope.clear = function() { - $scope.application.notBefore = 0; - Application.update({ realm : realm.realm, application: application.id}, $scope.application, function () { + $scope.client.notBefore = 0; + Client.update({ realm : realm.realm, client: client.id}, $scope.client, function () { $scope.notBefore = "None"; - Notifications.success('Not Before cleared for application.'); + Notifications.success('Not Before cleared for client.'); refresh(); }); } $scope.setNotBeforeNow = function() { - $scope.application.notBefore = new Date().getTime()/1000; - Application.update({ realm : realm.realm, application: $scope.application.id}, $scope.application, function () { - Notifications.success('Not Before set for application.'); + $scope.client.notBefore = new Date().getTime()/1000; + Client.update({ realm : realm.realm, client: $scope.client.id}, $scope.client, function () { + Notifications.success('Not Before set for client.'); refresh(); }); } $scope.pushRevocation = function() { - ApplicationPushRevocation.save({realm : realm.realm, application: $scope.application.id}, function (globalReqResult) { + ClientPushRevocation.save({realm : realm.realm, client: $scope.client.id}, function (globalReqResult) { var successCount = globalReqResult.successRequests ? globalReqResult.successRequests.length : 0; var failedCount = globalReqResult.failedRequests ? globalReqResult.failedRequests.length : 0; @@ -973,32 +960,32 @@ module.controller('ApplicationRevocationCtrl', function($scope, realm, applicati }); -module.controller('ApplicationClusteringCtrl', function($scope, application, Application, ApplicationTestNodesAvailable, realm, $location, $route, Notifications, TimeUnit) { - $scope.application = application; +module.controller('ClientClusteringCtrl', function($scope, client, Client, ClientTestNodesAvailable, realm, $location, $route, Notifications, TimeUnit) { + $scope.client = client; $scope.realm = realm; - var oldCopy = angular.copy($scope.application); + var oldCopy = angular.copy($scope.client); $scope.changed = false; - $scope.$watch('application', function() { - if (!angular.equals($scope.application, oldCopy)) { + $scope.$watch('client', function() { + if (!angular.equals($scope.client, oldCopy)) { $scope.changed = true; } }, true); - $scope.application.nodeReRegistrationTimeoutUnit = TimeUnit.autoUnit(application.nodeReRegistrationTimeout); - $scope.application.nodeReRegistrationTimeout = TimeUnit.toUnit(application.nodeReRegistrationTimeout, $scope.application.nodeReRegistrationTimeoutUnit); - $scope.$watch('application.nodeReRegistrationTimeoutUnit', function(to, from) { - $scope.application.nodeReRegistrationTimeout = TimeUnit.convert($scope.application.nodeReRegistrationTimeout, from, to); + $scope.client.nodeReRegistrationTimeoutUnit = TimeUnit.autoUnit(client.nodeReRegistrationTimeout); + $scope.client.nodeReRegistrationTimeout = TimeUnit.toUnit(client.nodeReRegistrationTimeout, $scope.client.nodeReRegistrationTimeoutUnit); + $scope.$watch('client.nodeReRegistrationTimeoutUnit', function(to, from) { + $scope.client.nodeReRegistrationTimeout = TimeUnit.convert($scope.client.nodeReRegistrationTimeout, from, to); }); $scope.save = function() { - var appCopy = angular.copy($scope.application); - delete appCopy['nodeReRegistrationTimeoutUnit']; - appCopy.nodeReRegistrationTimeout = TimeUnit.toSeconds($scope.application.nodeReRegistrationTimeout, $scope.application.nodeReRegistrationTimeoutUnit) - Application.update({ realm : realm.realm, application : application.id }, appCopy, function () { + var clientCopy = angular.copy($scope.client); + delete clientCopy['nodeReRegistrationTimeoutUnit']; + clientCopy.nodeReRegistrationTimeout = TimeUnit.toSeconds($scope.client.nodeReRegistrationTimeout, $scope.client.nodeReRegistrationTimeoutUnit) + Client.update({ realm : realm.realm, client : client.id }, clientCopy, function () { $route.reload(); - Notifications.success('Your changes have been saved to the application.'); + Notifications.success('Your changes have been saved to the client.'); }); }; @@ -1007,8 +994,7 @@ module.controller('ApplicationClusteringCtrl', function($scope, application, App }; $scope.testNodesAvailable = function() { - console.log('testNodesAvailable'); - ApplicationTestNodesAvailable.get({ realm : realm.realm, application : application.id }, function(globalReqResult) { + ClientTestNodesAvailable.get({ realm : realm.realm, client : client.id }, function(globalReqResult) { $route.reload(); var successCount = globalReqResult.successRequests ? globalReqResult.successRequests.length : 0; @@ -1025,12 +1011,12 @@ module.controller('ApplicationClusteringCtrl', function($scope, application, App }); }; - if (application.registeredNodes) { + if (client.registeredNodes) { var nodeRegistrations = []; - for (node in application.registeredNodes) { + for (node in client.registeredNodes) { reg = { host: node, - lastRegistration: new Date(application.registeredNodes[node] * 1000) + lastRegistration: new Date(client.registeredNodes[node] * 1000) } nodeRegistrations.push(reg); } @@ -1039,24 +1025,22 @@ module.controller('ApplicationClusteringCtrl', function($scope, application, App }; }); -module.controller('ApplicationClusteringNodeCtrl', function($scope, application, Application, ApplicationClusterNode, realm, $location, $routeParams, Notifications) { - $scope.application = application; +module.controller('ClientClusteringNodeCtrl', function($scope, client, Client, ClientClusterNode, realm, $location, $routeParams, Notifications) { + $scope.client = client; $scope.realm = realm; $scope.create = !$routeParams.node; $scope.save = function() { - console.log('registerNode: ' + $scope.node.host); - ApplicationClusterNode.save({ realm : realm.realm, application : application.id , node: $scope.node.host }, function() { + ClientClusterNode.save({ realm : realm.realm, client : client.id , node: $scope.node.host }, function() { Notifications.success('Node ' + $scope.node.host + ' registered successfully.'); - $location.url('/realms/' + realm.realm + '/applications/' + application.id + '/clustering'); + $location.url('/realms/' + realm.realm + '/clients/' + client.id + '/clustering'); }); } $scope.unregisterNode = function() { - console.log('unregisterNode: ' + $scope.node.host); - ApplicationClusterNode.remove({ realm : realm.realm, application : application.id , node: $scope.node.host }, function() { + ClientClusterNode.remove({ realm : realm.realm, client : client.id , node: $scope.node.host }, function() { Notifications.success('Node ' + $scope.node.host + ' unregistered successfully.'); - $location.url('/realms/' + realm.realm + '/applications/' + application.id + '/clustering'); + $location.url('/realms/' + realm.realm + '/clients/' + client.id + '/clustering'); }); } @@ -1064,7 +1048,7 @@ module.controller('ApplicationClusteringNodeCtrl', function($scope, application, $scope.node = {} $scope.registered = false; } else { - var lastRegTime = application.registeredNodes[$routeParams.node]; + var lastRegTime = client.registeredNodes[$routeParams.node]; if (lastRegTime) { $scope.registered = true; @@ -1082,16 +1066,16 @@ module.controller('ApplicationClusteringNodeCtrl', function($scope, application, } }); -module.controller('ApplicationProtocolMapperListCtrl', function($scope, realm, application, serverInfo, - ApplicationProtocolMappersByProtocol, +module.controller('ClientProtocolMapperListCtrl', function($scope, realm, client, serverInfo, + ClientProtocolMappersByProtocol, $http, $location, Dialog, Notifications) { $scope.realm = realm; - $scope.application = application; - if (application.protocol == null) { - application.protocol = 'openid-connect'; + $scope.client = client; + if (client.protocol == null) { + client.protocol = 'openid-connect'; } - var protocolMappers = serverInfo.protocolMapperTypes[application.protocol]; + var protocolMappers = serverInfo.protocolMapperTypes[client.protocol]; var mapperTypes = {}; for (var i = 0; i < protocolMappers.length; i++) { mapperTypes[protocolMappers[i].id] = protocolMappers[i]; @@ -1100,22 +1084,22 @@ module.controller('ApplicationProtocolMapperListCtrl', function($scope, realm, a var updateMappers = function() { - $scope.mappers = ApplicationProtocolMappersByProtocol.query({realm : realm.realm, application : application.id, protocol : application.protocol}); + $scope.mappers = ClientProtocolMappersByProtocol.query({realm : realm.realm, client : client.id, protocol : client.protocol}); }; updateMappers(); }); -module.controller('AddBuiltinProtocolMapperCtrl', function($scope, realm, application, serverInfo, - ApplicationProtocolMappersByProtocol, +module.controller('AddBuiltinProtocolMapperCtrl', function($scope, realm, client, serverInfo, + ClientProtocolMappersByProtocol, $http, $location, Dialog, Notifications) { $scope.realm = realm; - $scope.application = application; - if (application.protocol == null) { - application.protocol = 'openid-connect'; + $scope.client = client; + if (client.protocol == null) { + client.protocol = 'openid-connect'; } - var protocolMappers = serverInfo.protocolMapperTypes[application.protocol]; + var protocolMappers = serverInfo.protocolMapperTypes[client.protocol]; var mapperTypes = {}; for (var i = 0; i < protocolMappers.length; i++) { mapperTypes[protocolMappers[i].id] = protocolMappers[i]; @@ -1126,21 +1110,17 @@ module.controller('AddBuiltinProtocolMapperCtrl', function($scope, realm, applic var updateMappers = function() { - var appMappers = ApplicationProtocolMappersByProtocol.query({realm : realm.realm, application : application.id, protocol : application.protocol}, function() { - var builtinMappers = serverInfo.builtinProtocolMappers[application.protocol]; - for (var i = 0; i < appMappers.length; i++) { + var clientMappers = ClientProtocolMappersByProtocol.query({realm : realm.realm, client : client.id, protocol : client.protocol}, function() { + var builtinMappers = serverInfo.builtinProtocolMappers[client.protocol]; + for (var i = 0; i < clientMappers.length; i++) { for (var j = 0; j < builtinMappers.length; j++) { - if (builtinMappers[j].name == appMappers[i].name - && builtinMappers[j].protocolMapper == appMappers[i].protocolMapper) { - console.log('removing: ' + builtinMappers[j].name); + if (builtinMappers[j].name == clientMappers[i].name + && builtinMappers[j].protocolMapper == clientMappers[i].protocolMapper) { builtinMappers.splice(j, 1); break; } } } - for (var j = 0; j < builtinMappers.length; j++) { - console.log('builtin left: ' + builtinMappers[j].name); - } $scope.mappers = builtinMappers; for (var i = 0; i < $scope.mappers.length; i++) { $scope.mappers[i].isChecked = false; @@ -1160,32 +1140,32 @@ module.controller('AddBuiltinProtocolMapperCtrl', function($scope, realm, applic toAdd.push($scope.mappers[i]); } } - $http.post(authUrl + '/admin/realms/' + realm.realm + '/applications-by-id/' + application.id + '/protocol-mappers/add-models', + $http.post(authUrl + '/admin/realms/' + realm.realm + '/clients-by-id/' + client.id + '/protocol-mappers/add-models', toAdd).success(function() { Notifications.success("Mappers added"); - $location.url('/realms/' + realm.realm + '/applications/' + application.id + '/mappers'); + $location.url('/realms/' + realm.realm + '/clients/' + client.id + '/mappers'); }).error(function() { Notifications.error("Error adding mappers"); - $location.url('/realms/' + realm.realm + '/applications/' + application.id + '/mappers'); + $location.url('/realms/' + realm.realm + '/clients/' + client.id + '/mappers'); }); }; }); -module.controller('ApplicationProtocolMapperCtrl', function($scope, realm, serverInfo, application, mapper, ApplicationProtocolMapper, Notifications, Dialog, $location) { +module.controller('ClientProtocolMapperCtrl', function($scope, realm, serverInfo, client, mapper, ClientProtocolMapper, Notifications, Dialog, $location) { $scope.realm = realm; - $scope.application = application; + $scope.client = client; $scope.create = false; - if (application.protocol == null) { - application.protocol = 'openid-connect'; + if (client.protocol == null) { + client.protocol = 'openid-connect'; } - $scope.protocol = application.protocol; + $scope.protocol = client.protocol; $scope.mapper = angular.copy(mapper); $scope.changed = false; $scope.boolval = true; $scope.boolvalId = 'boolval'; - var protocolMappers = serverInfo.protocolMapperTypes[application.protocol]; + var protocolMappers = serverInfo.protocolMapperTypes[client.protocol]; for (var i = 0; i < protocolMappers.length; i++) { if (protocolMappers[i].id == mapper.protocolMapper) { $scope.mapperType = protocolMappers[i]; @@ -1204,14 +1184,14 @@ module.controller('ApplicationProtocolMapperCtrl', function($scope, realm, serve }, true); $scope.save = function() { - ApplicationProtocolMapper.update({ + ClientProtocolMapper.update({ realm : realm.realm, - application: application.id, + client: client.id, id : mapper.id }, $scope.mapper, function() { $scope.changed = false; mapper = angular.copy($scope.mapper); - $location.url("/realms/" + realm.realm + '/applications/' + application.id + "/mappers/" + mapper.id); + $location.url("/realms/" + realm.realm + '/clients/' + client.id + "/mappers/" + mapper.id); Notifications.success("Your changes have been saved."); }); }; @@ -1228,25 +1208,25 @@ module.controller('ApplicationProtocolMapperCtrl', function($scope, realm, serve $scope.remove = function() { Dialog.confirmDelete($scope.mapper.name, 'mapper', function() { - ApplicationProtocolMapper.remove({ realm: realm.realm, application: application.id, id : $scope.mapper.id }, function() { + ClientProtocolMapper.remove({ realm: realm.realm, client: client.id, id : $scope.mapper.id }, function() { Notifications.success("The mapper has been deleted."); - $location.url("/realms/" + realm.realm + '/applications/' + application.id + "/mappers"); + $location.url("/realms/" + realm.realm + '/clients/' + client.id + "/mappers"); }); }); }; }); -module.controller('ApplicationProtocolMapperCreateCtrl', function($scope, realm, serverInfo, application, ApplicationProtocolMapper, Notifications, Dialog, $location) { +module.controller('ClientProtocolMapperCreateCtrl', function($scope, realm, serverInfo, client, ClientProtocolMapper, Notifications, Dialog, $location) { $scope.realm = realm; - $scope.application = application; + $scope.client = client; $scope.create = true; - if (application.protocol == null) { - application.protocol = 'openid-connect'; + if (client.protocol == null) { + client.protocol = 'openid-connect'; } - var protocol = application.protocol; + var protocol = client.protocol; $scope.protocol = protocol; - $scope.mapper = { protocol : application.protocol, config: {}}; + $scope.mapper = { protocol : client.protocol, config: {}}; $scope.mapperTypes = serverInfo.protocolMapperTypes[protocol]; $scope.$watch(function() { @@ -1257,12 +1237,12 @@ module.controller('ApplicationProtocolMapperCreateCtrl', function($scope, realm, $scope.save = function() { $scope.mapper.protocolMapper = $scope.mapperType.id; - ApplicationProtocolMapper.save({ - realm : realm.realm, application: application.id + ClientProtocolMapper.save({ + realm : realm.realm, client: client.id }, $scope.mapper, function(data, headers) { var l = headers().location; var id = l.substring(l.lastIndexOf("/") + 1); - $location.url("/realms/" + realm.realm + '/applications/' + application.id + "/mappers/" + id); + $location.url("/realms/" + realm.realm + '/clients/' + client.id + "/mappers/" + id); Notifications.success("Mapper has been created."); }); }; diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/oauth-clients.js b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/oauth-clients.js deleted file mode 100755 index a55b9e3754..0000000000 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/oauth-clients.js +++ /dev/null @@ -1,611 +0,0 @@ -module.controller('OAuthClientClaimsCtrl', function($scope, realm, oauth, claims, - OAuthClientClaims, - $location, Dialog, Notifications) { - $scope.realm = realm; - $scope.oauth = oauth; - $scope.claims = angular.copy(claims); - - $scope.changed = false; - - $scope.$watch('claims', function () { - if (!angular.equals($scope.claims, claims)) { - $scope.changed = true; - } - }, true); - - - $scope.save = function () { - OAuthClientClaims.update({ - realm: realm.realm, - oauth: oauth.id - }, $scope.claims, function () { - $scope.changed = false; - claims = angular.copy($scope.claims); - - Notifications.success("Your claim changes have been saved."); - }); - }; - - $scope.reset = function () { - $location.url("/realms/" + realm.realm + "/oauth-clients/" + oauth.id + "/claims"); - }; - -}); - -module.controller('OAuthClientCredentialsCtrl', function($scope, $location, realm, oauth, OAuthClientCredentials, Notifications) { - $scope.realm = realm; - $scope.oauth = oauth; - - var secret = OAuthClientCredentials.get({ realm : realm.realm, oauth : oauth.id }, - function() { - $scope.secret = secret.value; - } - ); - - $scope.changePassword = function() { - var secret = OAuthClientCredentials.update({ realm : realm.realm, oauth : oauth.id }, - function() { - Notifications.success('The secret has been changed.'); - $scope.secret = secret.value; - }, - function() { - Notifications.error("The secret was not changed due to a problem."); - $scope.secret = "error"; - } - ); - }; - - $scope.$watch(function() { - return $location.path(); - }, function() { - $scope.path = $location.path().substring(1).split("/"); - }); - -}); - -module.controller('OAuthClientListCtrl', function($scope, realm, oauthClients, OAuthClient, $location) { - $scope.realm = realm; - $scope.oauthClients = oauthClients; - $scope.$watch(function() { - return $location.path(); - }, function() { - $scope.path = $location.path().substring(1).split("/"); - }); -}); - -module.controller('OAuthClientDetailCtrl', function($scope, realm, oauth, OAuthClient, $location, Dialog, Notifications) { - $scope.realm = realm; - $scope.create = !oauth.id; - - $scope.accessTypes = [ - "confidential", - "public" - ]; - - $scope.changeAccessType = function() { - if ($scope.accessType == "confidential") { - $scope.oauth.publicClient = false; - } else if ($scope.accessType == "public") { - $scope.oauth.publicClient = true; - } - }; - - - if (!$scope.create) { - $scope.oauth= angular.copy(oauth); - $scope.accessType = $scope.accessTypes[0]; - if (oauth.publicClient) { - $scope.accessType = $scope.accessTypes[1]; - } - } else { - $scope.oauth = { enabled: true }; - $scope.oauth.webOrigins = []; - $scope.oauth.redirectUris = []; - $scope.accessType = $scope.accessTypes[0]; - } - - $scope.$watch(function() { - return $location.path(); - }, function() { - $scope.path = $location.path().substring(1).split("/"); - }); - - $scope.$watch('oauth', function() { - if (!angular.equals($scope.oauth, oauth)) { - $scope.changed = true; - } - }, true); - - $scope.deleteWebOrigin = function(index) { - $scope.oauth.webOrigins.splice(index, 1); - } - $scope.addWebOrigin = function() { - $scope.oauth.webOrigins.push($scope.newWebOrigin); - $scope.newWebOrigin = ""; - } - $scope.deleteRedirectUri = function(index) { - $scope.oauth.redirectUris.splice(index, 1); - } - $scope.addRedirectUri = function() { - $scope.oauth.redirectUris.push($scope.newRedirectUri); - $scope.newRedirectUri = ""; - } - - $scope.save = function() { - if (!$scope.oauth.directGrantsOnly && (!$scope.oauth.redirectUris || $scope.oauth.redirectUris.length == 0)) { - Notifications.error("You must specify at least one redirect uri"); - } else { - if ($scope.create) { - OAuthClient.save({ - realm: realm.realm - }, $scope.oauth, function (data, headers) { - $scope.changed = false; - var l = headers().location; - var name = l.substring(l.lastIndexOf("/") + 1); - $location.url("/realms/" + realm.realm + "/oauth-clients/" + name); - Notifications.success("The oauth client has been created."); - }); - } else { - OAuthClient.update({ - realm : realm.realm, - oauth : oauth.id - }, $scope.oauth, function() { - $scope.changed = false; - oauth = angular.copy($scope.oauth); - $location.url("/realms/" + realm.realm + "/oauth-clients/" + oauth.id); - Notifications.success("Your changes have been saved to the oauth client."); - }); - } - } - }; - - $scope.reset = function() { - $scope.oauth = angular.copy(oauth); - $scope.changed = false; - }; - - $scope.cancel = function() { - $location.url("/realms/" + realm.realm + "/oauth-clients"); - }; - - $scope.remove = function() { - Dialog.confirmDelete($scope.oauth.id, 'oauth', function() { - $scope.oauth.$remove({ - realm : realm.realm, - oauth : $scope.oauth.id - }, function() { - $location.url("/realms/" + realm.realm + "/oauth-clients"); - Notifications.success("The oauth client has been deleted."); - }); - }); - }; - - -}); - -module.controller('OAuthClientScopeMappingCtrl', function($scope, $http, realm, oauth, applications, Notifications, - OAuthClient, - OAuthClientRealmScopeMapping, OAuthClientApplicationScopeMapping, ApplicationRole, - OAuthClientAvailableRealmScopeMapping, OAuthClientAvailableApplicationScopeMapping, - OAuthClientCompositeRealmScopeMapping, OAuthClientCompositeApplicationScopeMapping) { - $scope.realm = realm; - $scope.oauth = angular.copy(oauth); - $scope.selectedRealmRoles = []; - $scope.selectedRealmMappings = []; - $scope.realmMappings = []; - $scope.applications = applications; - $scope.applicationRoles = []; - $scope.applicationComposite = []; - $scope.selectedApplicationRoles = []; - $scope.selectedApplicationMappings = []; - $scope.applicationMappings = []; - $scope.dummymodel = []; - - $scope.changeFullScopeAllowed = function() { - console.log('change full scope'); - OAuthClient.update({ - realm : realm.realm, - oauth : oauth.id - }, $scope.oauth, function() { - $scope.changed = false; - oauth = angular.copy($scope.oauth); - Notifications.success("Scope mappings updated."); - }); - - } - - - function updateRealmRoles() { - $scope.realmRoles = OAuthClientAvailableRealmScopeMapping.query({realm : realm.realm, oauth : oauth.id}); - $scope.realmMappings = OAuthClientRealmScopeMapping.query({realm : realm.realm, oauth : oauth.id}); - $scope.realmComposite = OAuthClientCompositeRealmScopeMapping.query({realm : realm.realm, oauth : oauth.id}); - } - - function updateAppRoles() { - if ($scope.targetApp) { - console.debug($scope.targetApp.name); - $scope.applicationRoles = OAuthClientAvailableApplicationScopeMapping.query({realm : realm.realm, oauth : oauth.id, targetApp : $scope.targetApp.id}); - $scope.applicationMappings = OAuthClientApplicationScopeMapping.query({realm : realm.realm, oauth : oauth.id, targetApp : $scope.targetApp.id}); - $scope.applicationComposite = OAuthClientCompositeApplicationScopeMapping.query({realm : realm.realm, oauth : oauth.id, targetApp : $scope.targetApp.id}); - } else { - $scope.applicationRoles = null; - $scope.applicationMappings = null; - $scope.applicationComposite = null; - } - } - - $scope.changeApplication = function() { - updateAppRoles(); - }; - - $scope.addRealmRole = function() { - $http.post(authUrl + '/admin/realms/' + realm.realm + '/oauth-clients-by-id/' + oauth.id + '/scope-mappings/realm', - $scope.selectedRealmRoles).success(function () { - updateRealmRoles(); - Notifications.success("Scope mappings updated."); - }); - }; - - $scope.deleteRealmRole = function() { - $http.delete(authUrl + '/admin/realms/' + realm.realm + '/oauth-clients-by-id/' + oauth.id + '/scope-mappings/realm', - {data : $scope.selectedRealmMappings, headers : {"content-type" : "application/json"}}).success(function () { - updateRealmRoles(); - Notifications.success("Scope mappings updated."); - - }); - }; - - $scope.addApplicationRole = function() { - $http.post(authUrl + '/admin/realms/' + realm.realm + '/oauth-clients-by-id/' + oauth.id + '/scope-mappings/applications-by-id/' + $scope.targetApp.id, - $scope.selectedApplicationRoles).success(function () { - updateAppRoles(); - Notifications.success("Scope mappings updated."); - - }); - }; - - $scope.deleteApplicationRole = function() { - $http.delete(authUrl + '/admin/realms/' + realm.realm + '/oauth-clients-by-id/' + oauth.id + '/scope-mappings/applications-by-id/' + $scope.targetApp.id, - {data : $scope.selectedApplicationMappings, headers : {"content-type" : "application/json"}}).success(function () { - updateAppRoles(); - Notifications.success("Scope mappings updated."); - - }); - }; - - updateRealmRoles(); -}); - -module.controller('OAuthClientInstallationCtrl', function($scope, realm, installation, oauth, OAuthClientInstallation, $routeParams) { - $scope.realm = realm; - $scope.oauth = oauth; - $scope.installation = installation; - - $scope.download = function() { - saveAs(new Blob([angular.toJson($scope.installation, true)], { type: 'application/json' }), 'keycloak.json'); - } -}); - -module.controller('OAuthClientRevocationCtrl', function($scope, realm, oauth, OAuthClient, $location, Dialog, Notifications) { - $scope.oauth = oauth; - $scope.realm = realm; - var setNotBefore = function() { - if ($scope.oauth.notBefore == 0) { - $scope.notBefore = "None"; - } else { - $scope.notBefore = new Date($scope.oauth.notBefore * 1000); - } - }; - - setNotBefore(); - - var refresh = function() { - OAuthClient.get({ realm : realm.realm, oauth: $scope.oauth.id }, function(updated) { - $scope.oauth = updated; - setNotBefore(); - }) - - }; - - $scope.clear = function() { - $scope.oauth.notBefore = 0; - OAuthClient.update({ realm : realm.realm, oauth: $scope.oauth.id}, $scope.oauth, function () { - $scope.notBefore = "None"; - Notifications.success('Not Before cleared for application.'); - refresh(); - }); - } - $scope.setNotBeforeNow = function() { - $scope.oauth.notBefore = new Date().getTime()/1000; - OAuthClient.update({ realm : realm.realm, oauth: $scope.oauth.id}, $scope.oauth, function () { - Notifications.success('Not Before cleared for application.'); - refresh(); - }); - } -}); - -module.controller('OAuthClientIdentityProviderCtrl', function($scope, $route, realm, oauth, OAuthClient, $location, Notifications) { - $scope.realm = realm; - $scope.oauth = angular.copy(oauth); - var length = 0; - - if ($scope.oauth.identityProviders) { - length = $scope.oauth.identityProviders.length; - } else { - $scope.oauth.identityProviders = new Array(realm.identityProviders.length); - } - - for (j = length; j < realm.identityProviders.length; j++) { - $scope.oauth.identityProviders[j] = {}; - } - - $scope.identityProviders = []; - - for (j = 0; j < realm.identityProviders.length; j++) { - var identityProvider = realm.identityProviders[j]; - var match = false; - var applicationProvider; - - for (i = 0; i < $scope.oauth.identityProviders.length; i++) { - applicationProvider = $scope.oauth.identityProviders[i]; - - if (applicationProvider) { - if (applicationProvider.retrieveToken) { - applicationProvider.retrieveToken = applicationProvider.retrieveToken.toString(); - } else { - applicationProvider.retrieveToken = false.toString(); - } - - if (applicationProvider.id == identityProvider.id) { - $scope.identityProviders[i] = {}; - $scope.identityProviders[i].identityProvider = identityProvider; - $scope.identityProviders[i].retrieveToken = applicationProvider.retrieveToken.toString(); - break; - } - - applicationProvider = null; - } - } - - if (applicationProvider == null) { - var length = $scope.identityProviders.length + $scope.oauth.identityProviders.length; - - $scope.identityProviders[length] = {}; - $scope.identityProviders[length].identityProvider = identityProvider; - $scope.identityProviders[length].retrieveToken = false.toString(); - } - } - - $scope.identityProviders = $scope.identityProviders.filter(function(n){ return n != undefined }); - - var oldCopy = angular.copy($scope.oauth); - - $scope.save = function() { - var selectedProviders = []; - - for (i = 0; i < $scope.oauth.identityProviders.length; i++) { - var appProvider = $scope.oauth.identityProviders[i]; - - if (appProvider.id != null && appProvider.id != false) { - selectedProviders[selectedProviders.length] = appProvider; - } - } - - $scope.oauth.identityProviders = selectedProviders; - - OAuthClient.update({ - realm : realm.realm, - oauth : oauth.id - }, $scope.oauth, function() { - $scope.changed = false; - $route.reload(); - Notifications.success("Your changes have been saved to the application."); - }); - }; - - $scope.reset = function() { - $scope.oauth = angular.copy(oldCopy); - $scope.changed = false; - }; - - $scope.$watch('oauth', function() { - if (!angular.equals($scope.oauth, oldCopy)) { - $scope.changed = true; - } - }, true); -}); - -module.controller('OAuthClientProtocolMapperListCtrl', function($scope, realm, oauth, serverInfo, - OAuthClientProtocolMappersByProtocol, - $http, $location, Dialog, Notifications) { - $scope.realm = realm; - $scope.oauth = oauth; - if (oauth.protocol == null) { - oauth.protocol = 'openid-connect'; - } - - var protocolMappers = serverInfo.protocolMapperTypes[oauth.protocol]; - var mapperTypes = {}; - for (var i = 0; i < protocolMappers.length; i++) { - mapperTypes[protocolMappers[i].id] = protocolMappers[i]; - } - $scope.mapperTypes = mapperTypes; - - - var updateMappers = function() { - $scope.mappers = OAuthClientProtocolMappersByProtocol.query({realm : realm.realm, oauth : oauth.id, protocol : oauth.protocol}); - }; - - updateMappers(); -}); - -module.controller('OAuthClientAddBuiltinProtocolMapperCtrl', function($scope, realm, oauth, serverInfo, - OAuthClientProtocolMappersByProtocol, - $http, $location, Dialog, Notifications) { - $scope.realm = realm; - $scope.oauth = oauth; - if (oauth.protocol == null) { - oauth.protocol = 'openid-connect'; - } - - var protocolMappers = serverInfo.protocolMapperTypes[oauth.protocol]; - var mapperTypes = {}; - for (var i = 0; i < protocolMappers.length; i++) { - mapperTypes[protocolMappers[i].id] = protocolMappers[i]; - } - $scope.mapperTypes = mapperTypes; - - - - - var updateMappers = function() { - var appMappers = OAuthClientProtocolMappersByProtocol.query({realm : realm.realm, oauth : oauth.id, protocol : oauth.protocol}, function() { - var builtinMappers = serverInfo.builtinProtocolMappers[oauth.protocol]; - for (var i = 0; i < appMappers.length; i++) { - for (var j = 0; j < builtinMappers.length; j++) { - if (builtinMappers[j].name == appMappers[i].name - && builtinMappers[j].protocolMapper == appMappers[i].protocolMapper) { - console.log('removing: ' + builtinMappers[j].name); - builtinMappers.splice(j, 1); - break; - } - } - } - for (var j = 0; j < builtinMappers.length; j++) { - console.log('builtin left: ' + builtinMappers[j].name); - } - $scope.mappers = builtinMappers; - for (var i = 0; i < $scope.mappers.length; i++) { - $scope.mappers[i].isChecked = false; - } - - - }); - }; - - updateMappers(); - - $scope.add = function() { - var toAdd = []; - for (var i = 0; i < $scope.mappers.length; i++) { - if ($scope.mappers[i].isChecked) { - delete $scope.mappers[i].isChecked; - toAdd.push($scope.mappers[i]); - } - } - $http.post(authUrl + '/admin/realms/' + realm.realm + '/oauth-clients-by-id/' + oauth.id + '/protocol-mappers/add-models', - toAdd).success(function() { - Notifications.success("Mappers added"); - $location.url('/realms/' + realm.realm + '/oauth-clients/' + oauth.id + '/mappers'); - }).error(function() { - Notifications.error("Error adding mappers"); - $location.url('/realms/' + realm.realm + '/oauth-clients/' + oauth.id + '/mappers'); - }); - }; - -}); - -module.controller('OAuthClientProtocolMapperCtrl', function($scope, realm, serverInfo, oauth, mapper, OAuthClientProtocolMapper, Notifications, Dialog, $location) { - if (oauth.protocol == null) { - oauth.protocol = 'openid-connect'; - } - $scope.realm = realm; - $scope.oauth = oauth; - $scope.create = false; - var protocol = oauth.protocol; - $scope.protocol = oauth.protocol; - $scope.mapper = angular.copy(mapper); - var oldCopy = angular.copy($scope.realm); - $scope.changed = false; - - var protocolMappers = serverInfo.protocolMapperTypes[protocol]; - for (var i = 0; i < protocolMappers.length; i++) { - if (protocolMappers[i].id == mapper.protocolMapper) { - $scope.mapperType = protocolMappers[i]; - } - } - $scope.$watch(function() { - return $location.path(); - }, function() { - $scope.path = $location.path().substring(1).split("/"); - }); - - $scope.$watch('mapper', function() { - if (!angular.equals($scope.mapper, mapper)) { - $scope.changed = true; - } - }, true); - - $scope.save = function() { - OAuthClientProtocolMapper.update({ - realm : realm.realm, - oauth: oauth.id, - id : mapper.id - }, $scope.mapper, function() { - $scope.changed = false; - mapper = angular.copy($scope.mapper); - $location.url("/realms/" + realm.realm + '/oauth-clients/' + oauth.id + "/mappers/" + mapper.id); - Notifications.success("Your changes have been saved."); - }); - }; - - $scope.reset = function() { - $scope.mapper = angular.copy(mapper); - $scope.changed = false; - }; - - $scope.cancel = function() { - //$location.url("/realms"); - window.history.back(); - }; - - $scope.remove = function() { - Dialog.confirmDelete($scope.mapper.name, 'mapper', function() { - OAuthClientProtocolMapper.remove({ realm: realm.realm, oauth: oauth.id, id : $scope.mapper.id }, function() { - Notifications.success("The mapper has been deleted."); - $location.url("/realms/" + realm.realm + '/oauth-clients/' + oauth.id + "/mappers"); - }); - }); - }; - -}); - -module.controller('OAuthClientProtocolMapperCreateCtrl', function($scope, realm, serverInfo, oauth, OAuthClientProtocolMapper, Notifications, Dialog, $location) { - if (oauth.protocol == null) { - oauth.protocol = 'openid-connect'; - } - $scope.realm = realm; - $scope.oauth = oauth; - $scope.create = true; - var protocol = oauth.protocol; - $scope.protocol = protocol; - $scope.mapper = { protocol : oauth.protocol, config: {}}; - $scope.mapperTypes = serverInfo.protocolMapperTypes[protocol]; - - $scope.$watch(function() { - return $location.path(); - }, function() { - $scope.path = $location.path().substring(1).split("/"); - }); - - $scope.save = function() { - $scope.mapper.protocolMapper = $scope.mapperType.id; - OAuthClientProtocolMapper.save({ - realm : realm.realm, oauth: oauth.id - }, $scope.mapper, function(data, headers) { - var l = headers().location; - var id = l.substring(l.lastIndexOf("/") + 1); - $location.url("/realms/" + realm.realm + '/oauth-clients/' + oauth.id + "/mappers/" + id); - Notifications.success("Mapper has been created."); - }); - }; - - $scope.cancel = function() { - //$location.url("/realms"); - window.history.back(); - }; - - -}); - - diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js index bb7620e9e6..97c1bdaa7a 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js @@ -53,10 +53,6 @@ module.controller('GlobalCtrl', function($scope, $http, Auth, WhoAmI, Current, $ return getAccess('view-realm') || this.manageRealm; }, - get viewApplications() { - return getAccess('view-applications') || this.manageApplications; - }, - get viewClients() { return getAccess('view-clients') || this.manageClients; }, @@ -73,10 +69,6 @@ module.controller('GlobalCtrl', function($scope, $http, Auth, WhoAmI, Current, $ return getAccess('manage-realm'); }, - get manageApplications() { - return getAccess('manage-applications'); - }, - get manageClients() { return getAccess('manage-clients'); }, @@ -484,7 +476,7 @@ module.controller('RealmRequiredCredentialsCtrl', function($scope, Realm, realm, }; }); -module.controller('RealmDefaultRolesCtrl', function ($scope, Realm, realm, applications, roles, Notifications, ApplicationRole, Application) { +module.controller('RealmDefaultRolesCtrl', function ($scope, Realm, realm, clients, roles, Notifications, ClientRole, Client) { console.log('RealmDefaultRolesCtrl'); @@ -494,17 +486,17 @@ module.controller('RealmDefaultRolesCtrl', function ($scope, Realm, realm, appli $scope.selectedRealmRoles = []; $scope.selectedRealmDefRoles = []; - $scope.applications = angular.copy(applications); - for (var i = 0; i < applications.length; i++) { - if (applications[i].name == 'account') { - $scope.application = $scope.applications[i]; + $scope.clients = angular.copy(clients); + for (var i = 0; i < clients.length; i++) { + if (clients[i].name == 'account') { + $scope.client = $scope.clients[i]; break; } } - $scope.availableAppRoles = []; - $scope.selectedAppRoles = []; - $scope.selectedAppDefRoles = []; + $scope.availableClientRoles = []; + $scope.selectedClientRoles = []; + $scope.selectedClientDefRoles = []; if (!$scope.realm.hasOwnProperty('defaultRoles') || $scope.realm.defaultRoles === null) { $scope.realm.defaultRoles = []; @@ -558,81 +550,81 @@ module.controller('RealmDefaultRolesCtrl', function ($scope, Realm, realm, appli }); }; - $scope.changeApplication = function () { + $scope.changeClient = function () { - $scope.selectedAppRoles = []; - $scope.selectedAppDefRoles = []; + $scope.selectedClientRoles = []; + $scope.selectedClientDefRoles = []; - // Populate available roles for selected application - if ($scope.application) { - var appDefaultRoles = ApplicationRole.query({realm: $scope.realm.realm, application: $scope.application.id}, function () { + // Populate available roles for selected client + if ($scope.client) { + var appDefaultRoles = ClientRole.query({realm: $scope.realm.realm, client: $scope.client.id}, function () { - if (!$scope.application.hasOwnProperty('defaultRoles') || $scope.application.defaultRoles === null) { - $scope.application.defaultRoles = []; + if (!$scope.client.hasOwnProperty('defaultRoles') || $scope.client.defaultRoles === null) { + $scope.client.defaultRoles = []; } - $scope.availableAppRoles = []; + $scope.availableClientRoles = []; for (var i = 0; i < appDefaultRoles.length; i++) { var roleName = appDefaultRoles[i].name; - if ($scope.application.defaultRoles.indexOf(roleName) < 0) { - $scope.availableAppRoles.push(roleName); + if ($scope.client.defaultRoles.indexOf(roleName) < 0) { + $scope.availableClientRoles.push(roleName); } } }); } else { - $scope.availableAppRoles = null; + $scope.availableClientRoles = null; } }; - $scope.addAppDefaultRole = function () { + $scope.addClientDefaultRole = function () { // Remove selected roles from the app available roles and add them to app default roles (move from left to right). - for (var i = 0; i < $scope.selectedAppRoles.length; i++) { - var role = $scope.selectedAppRoles[i]; + for (var i = 0; i < $scope.selectedClientRoles.length; i++) { + var role = $scope.selectedClientRoles[i]; - var idx = $scope.application.defaultRoles.indexOf(role); + var idx = $scope.client.defaultRoles.indexOf(role); if (idx < 0) { - $scope.application.defaultRoles.push(role); + $scope.client.defaultRoles.push(role); } - idx = $scope.availableAppRoles.indexOf(role); + idx = $scope.availableClientRoles.indexOf(role); if (idx != -1) { - $scope.availableAppRoles.splice(idx, 1); + $scope.availableClientRoles.splice(idx, 1); } } - // Update/save the selected application with new default roles. - Application.update({ + // Update/save the selected client with new default roles. + Client.update({ realm: $scope.realm.realm, - application: $scope.application.id - }, $scope.application, function () { - Notifications.success("Your changes have been saved to the application."); + client: $scope.client.id + }, $scope.client, function () { + Notifications.success("Your changes have been saved to the client."); }); }; - $scope.rmAppDefaultRole = function () { + $scope.rmClientDefaultRole = function () { // Remove selected roles from the app default roles and add them to app available roles (move from right to left). - for (var i = 0; i < $scope.selectedAppDefRoles.length; i++) { - var role = $scope.selectedAppDefRoles[i]; - var idx = $scope.application.defaultRoles.indexOf(role); + for (var i = 0; i < $scope.selectedClientDefRoles.length; i++) { + var role = $scope.selectedClientDefRoles[i]; + var idx = $scope.client.defaultRoles.indexOf(role); if (idx != -1) { - $scope.application.defaultRoles.splice(idx, 1); + $scope.client.defaultRoles.splice(idx, 1); } - idx = $scope.availableAppRoles.indexOf(role); + idx = $scope.availableClientRoles.indexOf(role); if (idx < 0) { - $scope.availableAppRoles.push(role); + $scope.availableClientRoles.push(role); } } - // Update/save the selected application with new default roles. - Application.update({ + // Update/save the selected client with new default roles. + Client.update({ realm: $scope.realm.realm, - application: $scope.application.id - }, $scope.application, function () { - Notifications.success("Your changes have been saved to the application."); + client: $scope.client.id + }, $scope.client, function () { + Notifications.success("Your changes have been saved to the client."); }); }; @@ -856,7 +848,7 @@ module.controller('RealmIdentityProviderCtrl', function($scope, $filter, $upload alias : $scope.identityProvider.alias }, function() { $location.url("/realms/" + realm.realm + "/identity-provider-settings"); - Notifications.success("The application has been deleted."); + Notifications.success("The client has been deleted."); }); }); }; @@ -1016,7 +1008,7 @@ module.controller('RealmKeysDetailCtrl', function($scope, Realm, realm, $http, $ }; }); -module.controller('RealmSessionStatsCtrl', function($scope, realm, stats, RealmApplicationSessionStats, RealmLogoutAll, Notifications) { +module.controller('RealmSessionStatsCtrl', function($scope, realm, stats, RealmClientSessionStats, RealmLogoutAll, Notifications) { $scope.realm = realm; $scope.stats = stats; @@ -1081,7 +1073,7 @@ module.controller('RealmRevocationCtrl', function($scope, Realm, RealmPushRevoca var msgStart = successCount>0 ? 'Successfully push notBefore to: ' + globalReqResult.successRequests + ' . ' : ''; Notifications.error(msgStart + 'Failed to push notBefore to: ' + globalReqResult.failedRequests + '. Verify availability of failed hosts and try again'); } else { - Notifications.success('Successfully push notBefore to all configured applications'); + Notifications.success('Successfully push notBefore to all configured clients'); } }); } @@ -1102,8 +1094,8 @@ module.controller('RoleListCtrl', function($scope, $location, realm, roles) { }); -module.controller('RoleDetailCtrl', function($scope, realm, role, roles, applications, - Role, ApplicationRole, RoleById, RoleRealmComposites, RoleApplicationComposites, +module.controller('RoleDetailCtrl', function($scope, realm, role, roles, clients, + Role, ClientRole, RoleById, RoleRealmComposites, RoleClientComposites, $http, $location, Dialog, Notifications) { $scope.realm = realm; $scope.role = angular.copy(role); @@ -1149,8 +1141,8 @@ module.controller('RoleDetailCtrl', function($scope, realm, role, roles, applica - roleControl($scope, realm, role, roles, applications, - ApplicationRole, RoleById, RoleRealmComposites, RoleApplicationComposites, + roleControl($scope, realm, role, roles, clients, + ClientRole, RoleById, RoleRealmComposites, RoleClientComposites, $http, $location, Notifications, Dialog); }); diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/users.js b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/users.js index 3d50839a9c..30003bd05a 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/users.js +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/users.js @@ -1,17 +1,17 @@ -module.controller('UserRoleMappingCtrl', function($scope, $http, realm, user, applications, Notifications, RealmRoleMapping, - ApplicationRoleMapping, AvailableRealmRoleMapping, AvailableApplicationRoleMapping, - CompositeRealmRoleMapping, CompositeApplicationRoleMapping) { +module.controller('UserRoleMappingCtrl', function($scope, $http, realm, user, clients, Notifications, RealmRoleMapping, + ClientRoleMapping, AvailableRealmRoleMapping, AvailableClientRoleMapping, + CompositeRealmRoleMapping, CompositeClientRoleMapping) { $scope.realm = realm; $scope.user = user; $scope.selectedRealmRoles = []; $scope.selectedRealmMappings = []; $scope.realmMappings = []; - $scope.applications = applications; - $scope.applicationRoles = []; - $scope.applicationComposite = []; - $scope.selectedApplicationRoles = []; - $scope.selectedApplicationMappings = []; - $scope.applicationMappings = []; + $scope.clients = clients; + $scope.clientRoles = []; + $scope.clientComposite = []; + $scope.selectedClientRoles = []; + $scope.selectedClientMappings = []; + $scope.clientMappings = []; $scope.dummymodel = []; $scope.realmMappings = RealmRoleMapping.query({realm : realm.realm, userId : user.username}); @@ -26,13 +26,13 @@ module.controller('UserRoleMappingCtrl', function($scope, $http, realm, user, ap $scope.realmComposite = CompositeRealmRoleMapping.query({realm : realm.realm, userId : user.username}); $scope.selectedRealmMappings = []; $scope.selectRealmRoles = []; - if ($scope.application) { + if ($scope.client) { console.log('load available'); - $scope.applicationComposite = CompositeApplicationRoleMapping.query({realm : realm.realm, userId : user.username, application : $scope.application.id}); - $scope.applicationRoles = AvailableApplicationRoleMapping.query({realm : realm.realm, userId : user.username, application : $scope.application.id}); - $scope.applicationMappings = ApplicationRoleMapping.query({realm : realm.realm, userId : user.username, application : $scope.application.id}); - $scope.selectedApplicationRoles = []; - $scope.selectedApplicationMappings = []; + $scope.clientComposite = CompositeClientRoleMapping.query({realm : realm.realm, userId : user.username, client : $scope.client.id}); + $scope.clientRoles = AvailableClientRoleMapping.query({realm : realm.realm, userId : user.username, client : $scope.client.id}); + $scope.clientMappings = ClientRoleMapping.query({realm : realm.realm, userId : user.username, client : $scope.client.id}); + $scope.selectedClientRoles = []; + $scope.selectedClientMappings = []; } Notifications.success("Role mappings updated."); @@ -47,57 +47,57 @@ module.controller('UserRoleMappingCtrl', function($scope, $http, realm, user, ap $scope.realmComposite = CompositeRealmRoleMapping.query({realm : realm.realm, userId : user.username}); $scope.selectedRealmMappings = []; $scope.selectRealmRoles = []; - if ($scope.application) { + if ($scope.client) { console.log('load available'); - $scope.applicationComposite = CompositeApplicationRoleMapping.query({realm : realm.realm, userId : user.username, application : $scope.application.id}); - $scope.applicationRoles = AvailableApplicationRoleMapping.query({realm : realm.realm, userId : user.username, application : $scope.application.id}); - $scope.applicationMappings = ApplicationRoleMapping.query({realm : realm.realm, userId : user.username, application : $scope.application.id}); - $scope.selectedApplicationRoles = []; - $scope.selectedApplicationMappings = []; + $scope.clientComposite = CompositeClientRoleMapping.query({realm : realm.realm, userId : user.username, client : $scope.client.id}); + $scope.clientRoles = AvailableClientRoleMapping.query({realm : realm.realm, userId : user.username, client : $scope.client.id}); + $scope.clientMappings = ClientRoleMapping.query({realm : realm.realm, userId : user.username, client : $scope.client.id}); + $scope.selectedClientRoles = []; + $scope.selectedClientMappings = []; } Notifications.success("Role mappings updated."); }); }; - $scope.addApplicationRole = function() { - $http.post(authUrl + '/admin/realms/' + realm.realm + '/users/' + user.username + '/role-mappings/applications-by-id/' + $scope.application.id, - $scope.selectedApplicationRoles).success(function() { - $scope.applicationMappings = ApplicationRoleMapping.query({realm : realm.realm, userId : user.username, application : $scope.application.id}); - $scope.applicationRoles = AvailableApplicationRoleMapping.query({realm : realm.realm, userId : user.username, application : $scope.application.id}); - $scope.applicationComposite = CompositeApplicationRoleMapping.query({realm : realm.realm, userId : user.username, application : $scope.application.id}); - $scope.selectedApplicationRoles = []; - $scope.selectedApplicationMappings = []; + $scope.addClientRole = function() { + $http.post(authUrl + '/admin/realms/' + realm.realm + '/users/' + user.username + '/role-mappings/clients-by-id/' + $scope.client.id, + $scope.selectedClientRoles).success(function() { + $scope.clientMappings = ClientRoleMapping.query({realm : realm.realm, userId : user.username, client : $scope.client.id}); + $scope.clientRoles = AvailableClientRoleMapping.query({realm : realm.realm, userId : user.username, client : $scope.client.id}); + $scope.clientComposite = CompositeClientRoleMapping.query({realm : realm.realm, userId : user.username, client : $scope.client.id}); + $scope.selectedClientRoles = []; + $scope.selectedClientMappings = []; Notifications.success("Role mappings updated."); }); }; - $scope.deleteApplicationRole = function() { - $http.delete(authUrl + '/admin/realms/' + realm.realm + '/users/' + user.username + '/role-mappings/applications-by-id/' + $scope.application.id, - {data : $scope.selectedApplicationMappings, headers : {"content-type" : "application/json"}}).success(function() { - $scope.applicationMappings = ApplicationRoleMapping.query({realm : realm.realm, userId : user.username, application : $scope.application.id}); - $scope.applicationRoles = AvailableApplicationRoleMapping.query({realm : realm.realm, userId : user.username, application : $scope.application.id}); - $scope.applicationComposite = CompositeApplicationRoleMapping.query({realm : realm.realm, userId : user.username, application : $scope.application.id}); - $scope.selectedApplicationRoles = []; - $scope.selectedApplicationMappings = []; + $scope.deleteClientRole = function() { + $http.delete(authUrl + '/admin/realms/' + realm.realm + '/users/' + user.username + '/role-mappings/clients-by-id/' + $scope.client.id, + {data : $scope.selectedClientMappings, headers : {"content-type" : "application/json"}}).success(function() { + $scope.clientMappings = ClientRoleMapping.query({realm : realm.realm, userId : user.username, client : $scope.client.id}); + $scope.clientRoles = AvailableClientRoleMapping.query({realm : realm.realm, userId : user.username, client : $scope.client.id}); + $scope.clientComposite = CompositeClientRoleMapping.query({realm : realm.realm, userId : user.username, client : $scope.client.id}); + $scope.selectedClientRoles = []; + $scope.selectedClientMappings = []; Notifications.success("Role mappings updated."); }); }; - $scope.changeApplication = function() { - console.log('changeApplication'); - if ($scope.application) { + $scope.changeClient = function() { + console.log('changeClient'); + if ($scope.client) { console.log('load available'); - $scope.applicationComposite = CompositeApplicationRoleMapping.query({realm : realm.realm, userId : user.username, application : $scope.application.id}); - $scope.applicationRoles = AvailableApplicationRoleMapping.query({realm : realm.realm, userId : user.username, application : $scope.application.id}); - $scope.applicationMappings = ApplicationRoleMapping.query({realm : realm.realm, userId : user.username, application : $scope.application.id}); + $scope.clientComposite = CompositeClientRoleMapping.query({realm : realm.realm, userId : user.username, client : $scope.client.id}); + $scope.clientRoles = AvailableClientRoleMapping.query({realm : realm.realm, userId : user.username, client : $scope.client.id}); + $scope.clientMappings = ClientRoleMapping.query({realm : realm.realm, userId : user.username, client : $scope.client.id}); } else { - $scope.applicationRoles = null; - $scope.applicationMappings = null; - $scope.applicationComposite = null; + $scope.clientRoles = null; + $scope.clientMappings = null; + $scope.clientComposite = null; } - $scope.selectedApplicationRoles = []; - $scope.selectedApplicationMappings = []; + $scope.selectedClientRoles = []; + $scope.selectedClientMappings = []; }; @@ -111,7 +111,7 @@ module.controller('UserSessionsCtrl', function($scope, realm, user, sessions, Us $scope.logoutAll = function() { UserLogout.save({realm : realm.realm, user: user.username}, function () { - Notifications.success('Logged out user in all applications'); + Notifications.success('Logged out user in all clients'); UserSessions.query({realm: realm.realm, user: user.username}, function(updated) { $scope.sessions = updated; }) diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/loaders.js b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/loaders.js index da6873da34..b6e0541999 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/loaders.js +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/loaders.js @@ -71,35 +71,24 @@ module.factory('RealmSessionStatsLoader', function(Loader, RealmSessionStats, $r }); }); -module.factory('RealmApplicationSessionStatsLoader', function(Loader, RealmApplicationSessionStats, $route, $q) { - return Loader.query(RealmApplicationSessionStats, function() { +module.factory('RealmClientSessionStatsLoader', function(Loader, RealmClientSessionStats, $route, $q) { + return Loader.query(RealmClientSessionStats, function() { return { realm : $route.current.params.realm } }); }); -module.factory('ApplicationProtocolMapperLoader', function(Loader, ApplicationProtocolMapper, $route, $q) { - return Loader.get(ApplicationProtocolMapper, function() { +module.factory('ClientProtocolMapperLoader', function(Loader, ClientProtocolMapper, $route, $q) { + return Loader.get(ClientProtocolMapper, function() { return { realm : $route.current.params.realm, - application : $route.current.params.application, + client : $route.current.params.client, id: $route.current.params.id } }); }); -module.factory('OAuthClientProtocolMapperLoader', function(Loader, OAuthClientProtocolMapper, $route, $q) { - return Loader.get(OAuthClientProtocolMapper, function() { - return { - realm : $route.current.params.realm, - oauth : $route.current.params.oauth, - id: $route.current.params.id - } - }); -}); - - module.factory('UserLoader', function(Loader, User, $route, $q) { return Loader.get(User, function() { return { @@ -175,74 +164,74 @@ module.factory('RoleListLoader', function(Loader, Role, $route, $q) { }); }); -module.factory('ApplicationRoleLoader', function(Loader, RoleById, $route, $q) { +module.factory('ClientRoleLoader', function(Loader, RoleById, $route, $q) { return Loader.get(RoleById, function() { return { realm : $route.current.params.realm, - application : $route.current.params.application, + client : $route.current.params.client, role : $route.current.params.role } }); }); -module.factory('ApplicationSessionStatsLoader', function(Loader, ApplicationSessionStats, $route, $q) { - return Loader.get(ApplicationSessionStats, function() { +module.factory('ClientSessionStatsLoader', function(Loader, ClientSessionStats, $route, $q) { + return Loader.get(ClientSessionStats, function() { return { realm : $route.current.params.realm, - application : $route.current.params.application + client : $route.current.params.client } }); }); -module.factory('ApplicationSessionCountLoader', function(Loader, ApplicationSessionCount, $route, $q) { - return Loader.get(ApplicationSessionCount, function() { +module.factory('ClientSessionCountLoader', function(Loader, ClientSessionCount, $route, $q) { + return Loader.get(ClientSessionCount, function() { return { realm : $route.current.params.realm, - application : $route.current.params.application + client : $route.current.params.client } }); }); -module.factory('ApplicationClaimsLoader', function(Loader, ApplicationClaims, $route, $q) { - return Loader.get(ApplicationClaims, function() { +module.factory('ClientClaimsLoader', function(Loader, ClientClaims, $route, $q) { + return Loader.get(ClientClaims, function() { return { realm : $route.current.params.realm, - application : $route.current.params.application + client : $route.current.params.client } }); }); -module.factory('ApplicationInstallationLoader', function(Loader, ApplicationInstallation, $route, $q) { - return Loader.get(ApplicationInstallation, function() { +module.factory('ClientInstallationLoader', function(Loader, ClientInstallation, $route, $q) { + return Loader.get(ClientInstallation, function() { return { realm : $route.current.params.realm, - application : $route.current.params.application + client : $route.current.params.client } }); }); -module.factory('ApplicationRoleListLoader', function(Loader, ApplicationRole, $route, $q) { - return Loader.query(ApplicationRole, function() { +module.factory('ClientRoleListLoader', function(Loader, ClientRole, $route, $q) { + return Loader.query(ClientRole, function() { return { realm : $route.current.params.realm, - application : $route.current.params.application + client : $route.current.params.client } }); }); -module.factory('ApplicationLoader', function(Loader, Application, $route, $q) { - return Loader.get(Application, function() { +module.factory('ClientLoader', function(Loader, Client, $route, $q) { + return Loader.get(Client, function() { return { realm : $route.current.params.realm, - application : $route.current.params.application + client : $route.current.params.client } }); }); -module.factory('ApplicationListLoader', function(Loader, Application, $route, $q) { - return Loader.query(Application, function() { +module.factory('ClientListLoader', function(Loader, Client, $route, $q) { + return Loader.query(Client, function() { return { realm : $route.current.params.realm } @@ -251,7 +240,7 @@ module.factory('ApplicationListLoader', function(Loader, Application, $route, $q module.factory('RoleMappingLoader', function(Loader, RoleMapping, $route, $q) { - var realm = $route.current.params.realm || $route.current.params.application; + var realm = $route.current.params.realm || $route.current.params.client; return Loader.query(RoleMapping, function() { return { @@ -261,42 +250,6 @@ module.factory('RoleMappingLoader', function(Loader, RoleMapping, $route, $q) { }); }); -module.factory('OAuthClientLoader', function(Loader, OAuthClient, $route, $q) { - return Loader.get(OAuthClient, function() { - return { - realm : $route.current.params.realm, - oauth : $route.current.params.oauth - } - }); -}); - -module.factory('OAuthClientClaimsLoader', function(Loader, OAuthClientClaims, $route, $q) { - return Loader.get(OAuthClientClaims, function() { - return { - realm : $route.current.params.realm, - oauth : $route.current.params.oauth - } - }); -}); - - -module.factory('OAuthClientListLoader', function(Loader, OAuthClient, $route, $q) { - return Loader.query(OAuthClient, function() { - return { - realm : $route.current.params.realm - } - }); -}); - -module.factory('OAuthClientInstallationLoader', function(Loader, OAuthClientInstallation, $route, $q) { - return Loader.get(OAuthClientInstallation, function() { - return { - realm : $route.current.params.realm, - oauth : $route.current.params.oauth - } - }); -}); - module.factory('IdentityProviderLoader', function(Loader, IdentityProvider, $route, $q) { return Loader.get(IdentityProvider, function () { return { diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/services.js b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/services.js index d7833249cd..da0b2eb1a7 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/services.js +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/services.js @@ -190,10 +190,10 @@ module.factory('ServerInfo', function($resource) { -module.factory('ApplicationProtocolMapper', function($resource) { - return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/protocol-mappers/models/:id', { +module.factory('ClientProtocolMapper', function($resource) { + return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/protocol-mappers/models/:id', { realm : '@realm', - application: '@application', + client: '@client', id : "@id" }, { update : { @@ -202,29 +202,6 @@ module.factory('ApplicationProtocolMapper', function($resource) { }); }); -module.factory('OAuthClientProtocolMapper', function($resource) { - return $resource(authUrl + '/admin/realms/:realm/oauth-clients-by-id/:oauth/protocol-mappers/models/:id', { - realm : '@realm', - oauth: '@oauth', - id : "@id" - }, { - update : { - method : 'PUT' - } - }); -}); - -module.factory('OAuthClientProtocolMappersByProtocol', function($resource) { - return $resource(authUrl + '/admin/realms/:realm/oauth-clients-by-id/:oauth/protocol-mappers/protocol/:protocol', { - realm : '@realm', - oauth : "@oauth", - protocol : "@protocol" - }); -}); - - - - module.factory('User', function($resource) { return $resource(authUrl + '/admin/realms/:realm/users/:userId', { realm : '@realm', @@ -347,72 +324,72 @@ module.factory('AvailableRealmRoleMapping', function($resource) { }); -module.factory('ApplicationRoleMapping', function($resource) { - return $resource(authUrl + '/admin/realms/:realm/users/:userId/role-mappings/applications-by-id/:application', { +module.factory('ClientRoleMapping', function($resource) { + return $resource(authUrl + '/admin/realms/:realm/users/:userId/role-mappings/clients-by-id/:client', { realm : '@realm', userId : '@userId', - application : "@application" + client : "@client" }); }); -module.factory('AvailableApplicationRoleMapping', function($resource) { - return $resource(authUrl + '/admin/realms/:realm/users/:userId/role-mappings/applications-by-id/:application/available', { +module.factory('AvailableClientRoleMapping', function($resource) { + return $resource(authUrl + '/admin/realms/:realm/users/:userId/role-mappings/clients-by-id/:client/available', { realm : '@realm', userId : '@userId', - application : "@application" + client : "@client" }); }); -module.factory('CompositeApplicationRoleMapping', function($resource) { - return $resource(authUrl + '/admin/realms/:realm/users/:userId/role-mappings/applications-by-id/:application/composite', { +module.factory('CompositeClientRoleMapping', function($resource) { + return $resource(authUrl + '/admin/realms/:realm/users/:userId/role-mappings/clients-by-id/:client/composite', { realm : '@realm', userId : '@userId', - application : "@application" + client : "@client" }); }); -module.factory('ApplicationRealmScopeMapping', function($resource) { - return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/scope-mappings/realm', { +module.factory('ClientRealmScopeMapping', function($resource) { + return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/scope-mappings/realm', { realm : '@realm', - application : '@application' + client : '@client' }); }); -module.factory('ApplicationAvailableRealmScopeMapping', function($resource) { - return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/scope-mappings/realm/available', { +module.factory('ClientAvailableRealmScopeMapping', function($resource) { + return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/scope-mappings/realm/available', { realm : '@realm', - application : '@application' + client : '@client' }); }); -module.factory('ApplicationCompositeRealmScopeMapping', function($resource) { - return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/scope-mappings/realm/composite', { +module.factory('ClientCompositeRealmScopeMapping', function($resource) { + return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/scope-mappings/realm/composite', { realm : '@realm', - application : '@application' + client : '@client' }); }); -module.factory('ApplicationApplicationScopeMapping', function($resource) { - return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/scope-mappings/applications-by-id/:targetApp', { +module.factory('ClientClientScopeMapping', function($resource) { + return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/scope-mappings/clients-by-id/:targetClient', { realm : '@realm', - application : '@application', - targetApp : '@targetApp' + client : '@client', + targetClient : '@targetClient' }); }); -module.factory('ApplicationAvailableApplicationScopeMapping', function($resource) { - return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/scope-mappings/applications-by-id/:targetApp/available', { +module.factory('ClientAvailableClientScopeMapping', function($resource) { + return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/scope-mappings/clients-by-id/:targetClient/available', { realm : '@realm', - application : '@application', - targetApp : '@targetApp' + client : '@client', + targetClient : '@targetClient' }); }); -module.factory('ApplicationCompositeApplicationScopeMapping', function($resource) { - return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/scope-mappings/applications-by-id/:targetApp/composite', { +module.factory('ClientCompositeClientScopeMapping', function($resource) { + return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/scope-mappings/clients-by-id/:targetClient/composite', { realm : '@realm', - application : '@application', - targetApp : '@targetApp' + client : '@client', + targetClient : '@targetClient' }); }); @@ -443,24 +420,24 @@ module.factory('RealmSessionStats', function($resource) { }); }); -module.factory('RealmApplicationSessionStats', function($resource) { - return $resource(authUrl + '/admin/realms/:realm/application-by-id-session-stats', { +module.factory('RealmClientSessionStats', function($resource) { + return $resource(authUrl + '/admin/realms/:realm/client-by-id-session-stats', { realm : '@realm' }); }); -module.factory('RoleApplicationComposites', function($resource) { - return $resource(authUrl + '/admin/realms/:realm/roles-by-id/:role/composites/applications-by-id/:application', { +module.factory('RoleClientComposites', function($resource) { + return $resource(authUrl + '/admin/realms/:realm/roles-by-id/:role/composites/clients-by-id/:client', { realm : '@realm', role : '@role', - application : "@application" + client : "@client" }); }); -function roleControl($scope, realm, role, roles, applications, - ApplicationRole, RoleById, RoleRealmComposites, RoleApplicationComposites, +function roleControl($scope, realm, role, roles, clients, + ClientRole, RoleById, RoleRealmComposites, RoleClientComposites, $http, $location, Notifications, Dialog) { $scope.$watch(function () { @@ -499,11 +476,11 @@ function roleControl($scope, realm, role, roles, applications, $scope.selectedRealmRoles = []; $scope.selectedRealmMappings = []; $scope.realmMappings = []; - $scope.applications = applications; - $scope.applicationRoles = []; - $scope.selectedApplicationRoles = []; - $scope.selectedApplicationMappings = []; - $scope.applicationMappings = []; + $scope.clients = clients; + $scope.clientRoles = []; + $scope.selectedClientRoles = []; + $scope.selectedClientMappings = []; + $scope.clientMappings = []; for (var j = 0; j < $scope.realmRoles.length; j++) { if ($scope.realmRoles[j].id == role.id) { @@ -563,61 +540,61 @@ function roleControl($scope, realm, role, roles, applications, }); }; - $scope.addApplicationRole = function() { + $scope.addClientRole = function() { $scope.compositeSwitchDisabled=true; $http.post(authUrl + '/admin/realms/' + realm.realm + '/roles-by-id/' + role.id + '/composites', - $scope.selectedApplicationRoles).success(function() { - for (var i = 0; i < $scope.selectedApplicationRoles.length; i++) { - var role = $scope.selectedApplicationRoles[i]; - var idx = $scope.applicationRoles.indexOf($scope.selectedApplicationRoles[i]); + $scope.selectedClientRoles).success(function() { + for (var i = 0; i < $scope.selectedClientRoles.length; i++) { + var role = $scope.selectedClientRoles[i]; + var idx = $scope.clientRoles.indexOf($scope.selectedClientRoles[i]); if (idx != -1) { - $scope.applicationRoles.splice(idx, 1); - $scope.applicationMappings.push(role); + $scope.clientRoles.splice(idx, 1); + $scope.clientMappings.push(role); } } - $scope.selectedApplicationRoles = []; + $scope.selectedClientRoles = []; }); }; - $scope.deleteApplicationRole = function() { + $scope.deleteClientRole = function() { $scope.compositeSwitchDisabled=true; $http.delete(authUrl + '/admin/realms/' + realm.realm + '/roles-by-id/' + role.id + '/composites', - {data : $scope.selectedApplicationMappings, headers : {"content-type" : "application/json"}}).success(function() { - for (var i = 0; i < $scope.selectedApplicationMappings.length; i++) { - var role = $scope.selectedApplicationMappings[i]; - var idx = $scope.applicationMappings.indexOf($scope.selectedApplicationMappings[i]); + {data : $scope.selectedClientMappings, headers : {"content-type" : "application/json"}}).success(function() { + for (var i = 0; i < $scope.selectedClientMappings.length; i++) { + var role = $scope.selectedClientMappings[i]; + var idx = $scope.clientMappings.indexOf($scope.selectedClientMappings[i]); if (idx != -1) { - $scope.applicationMappings.splice(idx, 1); - $scope.applicationRoles.push(role); + $scope.clientMappings.splice(idx, 1); + $scope.clientRoles.push(role); } } - $scope.selectedApplicationMappings = []; + $scope.selectedClientMappings = []; }); }; - $scope.changeApplication = function() { - $scope.applicationRoles = ApplicationRole.query({realm : realm.realm, application : $scope.compositeApp.id}, function() { - $scope.applicationMappings = RoleApplicationComposites.query({realm : realm.realm, role : role.id, application : $scope.compositeApp.id}, function(){ - for (var i = 0; i < $scope.applicationMappings.length; i++) { - var role = $scope.applicationMappings[i]; - for (var j = 0; j < $scope.applicationRoles.length; j++) { - var realmRole = $scope.applicationRoles[j]; + $scope.changeClient = function() { + $scope.clientRoles = ClientRole.query({realm : realm.realm, client : $scope.compositeClient.id}, function() { + $scope.clientMappings = RoleClientComposites.query({realm : realm.realm, role : role.id, client : $scope.compositeClient.id}, function(){ + for (var i = 0; i < $scope.clientMappings.length; i++) { + var role = $scope.clientMappings[i]; + for (var j = 0; j < $scope.clientRoles.length; j++) { + var realmRole = $scope.clientRoles[j]; if (realmRole.id == role.id) { - var idx = $scope.applicationRoles.indexOf(realmRole); + var idx = $scope.clientRoles.indexOf(realmRole); if (idx != -1) { - $scope.applicationRoles.splice(idx, 1); + $scope.clientRoles.splice(idx, 1); break; } } } } }); - for (var j = 0; j < $scope.applicationRoles.length; j++) { - if ($scope.applicationRoles[j] == role.id) { - var appRole = $scope.applicationRoles[j]; - var idx = $scope.applicationRoles.indexof(appRole); - $scope.applicationRoles.splice(idx, 1); + for (var j = 0; j < $scope.clientRoles.length; j++) { + if ($scope.clientRoles[j] == role.id) { + var appRole = $scope.clientRoles[j]; + var idx = $scope.clientRoles.indexof(appRole); + $scope.clientRoles.splice(idx, 1); break; } } @@ -653,10 +630,10 @@ module.factory('RoleById', function($resource) { }); }); -module.factory('ApplicationRole', function($resource) { - return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/roles/:role', { +module.factory('ClientRole', function($resource) { + return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/roles/:role', { realm : '@realm', - application : "@application", + client : "@client", role : '@role' }, { update : { @@ -665,10 +642,10 @@ module.factory('ApplicationRole', function($resource) { }); }); -module.factory('ApplicationClaims', function($resource) { - return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/claims', { +module.factory('ClientClaims', function($resource) { + return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/claims', { realm : '@realm', - application : "@application" + client : "@client" }, { update : { method : 'PUT' @@ -676,52 +653,52 @@ module.factory('ApplicationClaims', function($resource) { }); }); -module.factory('ApplicationProtocolMappersByProtocol', function($resource) { - return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/protocol-mappers/protocol/:protocol', { +module.factory('ClientProtocolMappersByProtocol', function($resource) { + return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/protocol-mappers/protocol/:protocol', { realm : '@realm', - application : "@application", + client : "@client", protocol : "@protocol" }); }); -module.factory('ApplicationSessionStats', function($resource) { - return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/session-stats', { +module.factory('ClientSessionStats', function($resource) { + return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/session-stats', { realm : '@realm', - application : "@application" + client : "@client" }); }); -module.factory('ApplicationSessionStatsWithUsers', function($resource) { - return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/session-stats?users=true', { +module.factory('ClientSessionStatsWithUsers', function($resource) { + return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/session-stats?users=true', { realm : '@realm', - application : "@application" + client : "@client" }); }); -module.factory('ApplicationSessionCount', function($resource) { - return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/session-count', { +module.factory('ClientSessionCount', function($resource) { + return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/session-count', { realm : '@realm', - application : "@application" + client : "@client" }); }); -module.factory('ApplicationUserSessions', function($resource) { - return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/user-sessions', { +module.factory('ClientUserSessions', function($resource) { + return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/user-sessions', { realm : '@realm', - application : "@application" + client : "@client" }); }); -module.factory('ApplicationLogoutAll', function($resource) { - return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/logout-all', { +module.factory('ClientLogoutAll', function($resource) { + return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/logout-all', { realm : '@realm', - application : "@application" + client : "@client" }); }); -module.factory('ApplicationLogoutUser', function($resource) { - return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/logout-user/:user', { +module.factory('ClientLogoutUser', function($resource) { + return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/logout-user/:user', { realm : '@realm', - application : "@application", + client : "@client", user : "@user" }); }); @@ -731,39 +708,39 @@ module.factory('RealmLogoutAll', function($resource) { }); }); -module.factory('ApplicationPushRevocation', function($resource) { - return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/push-revocation', { +module.factory('ClientPushRevocation', function($resource) { + return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/push-revocation', { realm : '@realm', - application : "@application" + client : "@client" }); }); -module.factory('ApplicationClusterNode', function($resource) { - return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/nodes/:node', { +module.factory('ClientClusterNode', function($resource) { + return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/nodes/:node', { realm : '@realm', - application : "@application" + client : "@client" }); }); -module.factory('ApplicationTestNodesAvailable', function($resource) { - return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/test-nodes-available', { +module.factory('ClientTestNodesAvailable', function($resource) { + return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/test-nodes-available', { realm : '@realm', - application : "@application" + client : "@client" }); }); -module.factory('ApplicationCertificate', function($resource) { - return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/certificates/:attribute', { +module.factory('ClientCertificate', function($resource) { + return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/certificates/:attribute', { realm : '@realm', - application : "@application", + client : "@client", attribute: "@attribute" }); }); -module.factory('ApplicationCertificateGenerate', function($resource) { - return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/certificates/:attribute/generate', { +module.factory('ClientCertificateGenerate', function($resource) { + return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/certificates/:attribute/generate', { realm : '@realm', - application : "@application", + client : "@client", attribute: "@attribute" }, { @@ -773,10 +750,10 @@ module.factory('ApplicationCertificateGenerate', function($resource) { }); }); -module.factory('ApplicationCertificateDownload', function($resource) { - return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/certificates/:attribute/download', { +module.factory('ClientCertificateDownload', function($resource) { + return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/certificates/:attribute/download', { realm : '@realm', - application : "@application", + client : "@client", attribute: "@attribute" }, { @@ -787,10 +764,10 @@ module.factory('ApplicationCertificateDownload', function($resource) { }); }); -module.factory('Application', function($resource) { - return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application', { +module.factory('Client', function($resource) { + return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client', { realm : '@realm', - application : '@application' + client : '@client' }, { update : { method : 'PUT' @@ -798,29 +775,29 @@ module.factory('Application', function($resource) { }); }); -module.factory('ApplicationInstallation', function($resource) { - var url = authUrl + '/admin/realms/:realm/applications-by-id/:application/installation/json'; +module.factory('ClientInstallation', function($resource) { + var url = authUrl + '/admin/realms/:realm/clients-by-id/:client/installation/json'; return { url : function(parameters) { - return url.replace(':realm', parameters.realm).replace(':application', parameters.application); + return url.replace(':realm', parameters.realm).replace(':client', parameters.client); } } }); -module.factory('ApplicationInstallationJBoss', function($resource) { - var url = authUrl + '/admin/realms/:realm/applications-by-id/:application/installation/jboss'; +module.factory('ClientInstallationJBoss', function($resource) { + var url = authUrl + '/admin/realms/:realm/clients-by-id/:client/installation/jboss'; return { url : function(parameters) { - return url.replace(':realm', parameters.realm).replace(':application', parameters.application); + return url.replace(':realm', parameters.realm).replace(':client', parameters.client); } } }); -module.factory('ApplicationCredentials', function($resource) { - return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/client-secret', { +module.factory('ClientCredentials', function($resource) { + return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/client-secret', { realm : '@realm', - application : '@application' + client : '@client' }, { update : { method : 'POST' @@ -828,10 +805,10 @@ module.factory('ApplicationCredentials', function($resource) { }); }); -module.factory('ApplicationOrigins', function($resource) { - return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/allowed-origins', { +module.factory('ClientOrigins', function($resource) { + return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/allowed-origins', { realm : '@realm', - application : '@application' + client : '@client' }, { update : { method : 'PUT', @@ -840,127 +817,13 @@ module.factory('ApplicationOrigins', function($resource) { }); }); -module.factory('OAuthClient', function($resource) { - return $resource(authUrl + '/admin/realms/:realm/oauth-clients-by-id/:oauth', { - realm : '@realm', - oauth : '@oauth' - }, { - update : { - method : 'PUT' - } - }); -}); - -module.factory('OAuthClientClaims', function($resource) { - return $resource(authUrl + '/admin/realms/:realm/oauth-clients-by-id/:oauth/claims', { - realm : '@realm', - oauth : "@oauth" - }, { - update : { - method : 'PUT' - } - }); -}); - - -module.factory('OAuthClientCredentials', function($resource) { - return $resource(authUrl + '/admin/realms/:realm/oauth-clients-by-id/:oauth/client-secret', { - realm : '@realm', - oauth : '@oauth' - }, { - update : { - method : 'POST' - } - }); - -}); - -module.factory('OAuthCertificate', function($resource) { - return $resource(authUrl + '/admin/realms/:realm/oauth-clients-by-id/:oauth/certificates', { - realm : '@realm', - oauth : '@oauth' - }); -}); - -module.factory('OAuthCertificateDownload', function($resource) { - return $resource(authUrl + '/admin/realms/:realm/oauth-clients-by-id/:oauth/certificates/download', { - realm : '@realm', - oauth : '@oauth' - }); -}); - - -module.factory('OAuthClientRealmScopeMapping', function($resource) { - return $resource(authUrl + '/admin/realms/:realm/oauth-clients-by-id/:oauth/scope-mappings/realm', { - realm : '@realm', - oauth : '@oauth' - }); -}); - -module.factory('OAuthClientCompositeRealmScopeMapping', function($resource) { - return $resource(authUrl + '/admin/realms/:realm/oauth-clients-by-id/:oauth/scope-mappings/realm/composite', { - realm : '@realm', - oauth : '@oauth' - }); -}); - -module.factory('OAuthClientAvailableRealmScopeMapping', function($resource) { - return $resource(authUrl + '/admin/realms/:realm/oauth-clients-by-id/:oauth/scope-mappings/realm/available', { - realm : '@realm', - oauth : '@oauth' - }); -}); - -module.factory('OAuthClientApplicationScopeMapping', function($resource) { - return $resource(authUrl + '/admin/realms/:realm/oauth-clients-by-id/:oauth/scope-mappings/applications-by-id/:targetApp', { - realm : '@realm', - oauth : '@oauth', - targetApp : '@targetApp' - }); -}); - -module.factory('OAuthClientCompositeApplicationScopeMapping', function($resource) { - return $resource(authUrl + '/admin/realms/:realm/oauth-clients-by-id/:oauth/scope-mappings/applications-by-id/:targetApp/composite', { - realm : '@realm', - oauth : '@oauth', - targetApp : '@targetApp' - }); -}); - -module.factory('OAuthClientAvailableApplicationScopeMapping', function($resource) { - return $resource(authUrl + '/admin/realms/:realm/oauth-clients-by-id/:oauth/scope-mappings/applications-by-id/:targetApp/available', { - realm : '@realm', - oauth : '@oauth', - targetApp : '@targetApp' - }); -}); - - - -module.factory('OAuthClientInstallation', function($resource) { - var url = authUrl + '/admin/realms/:realm/oauth-clients-by-id/:oauth/installation'; - var resource = $resource(authUrl + '/admin/realms/:realm/oauth-clients-by-id/:oauth/installation', { - realm : '@realm', - oauth : '@oauth' - }, { - update : { - method : 'PUT' - } - }); - resource.url = function(parameters) { - return url.replace(':realm', parameters.realm).replace(':oauth', parameters.oauth); - } - return resource; -}); - - module.factory('Current', function(Realm, $route) { var current = {}; current.realms = {}; current.realm = null; - current.applications = {}; - current.application = null; + current.clients = {}; + current.client = null; current.refresh = function() { current.realm = null; diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-list.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-list.html deleted file mode 100755 index 92bb4af983..0000000000 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-list.html +++ /dev/null @@ -1,59 +0,0 @@ -
    -
    -

    -
    -

    {{realm.realm}} Applications

    - - - - - - - - - - - - - - - - - - - - - -
    -
    - - -
    -
    - Import - Create -
    -
    Application NameEnabledBase URL
    {{app.name}}{{app.enabled}} - {{app.baseUrl}} - Not defined -
    No applications available
    - -
    -
    \ No newline at end of file diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-mappers.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-mappers.html deleted file mode 100755 index c9c14fede4..0000000000 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-mappers.html +++ /dev/null @@ -1,47 +0,0 @@ -
    -
    - -
    - -

    {{realm.realm}} {{application.name}} {{application.protocol}} Protocol Mappers

    - - - - - - - - - - - - - - - - - - - - - -
    -
    - - -
    - -
    NameCategoryType
    {{mapper.name}}{{mapperTypes[mapper.protocolMapper].category}}{{mapperTypes[mapper.protocolMapper].name}}
    No mappers available
    -
    -
    diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-clustering-node.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-clustering-node.html similarity index 75% rename from forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-clustering-node.html rename to forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-clustering-node.html index 74ef211f37..d959154e16 100644 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-clustering-node.html +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-clustering-node.html @@ -1,16 +1,16 @@
    - +
    -

    {{application.name}} Clustering

    +

    {{client.clientId}} Clustering

    Cluster node on host {{node.host}} not registered!

    -
    +
    Configuration of cluster node
    diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-clustering.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-clustering.html similarity index 76% rename from forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-clustering.html rename to forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-clustering.html index 985260fea5..cedd87d551 100644 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-clustering.html +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-clustering.html @@ -1,14 +1,14 @@
    - +
    -

    {{application.name}} Clustering

    - +

    {{client.clientId}} Clustering

    + Basic configuration
    @@ -17,12 +17,12 @@
    - + @@ -30,7 +30,7 @@
    - +
    @@ -43,10 +43,10 @@ - @@ -57,7 +57,7 @@ - + diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-credentials.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-credentials.html similarity index 71% rename from forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-credentials.html rename to forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-credentials.html index f8cc47acfb..fdb8ceeae3 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-credentials.html +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-credentials.html @@ -1,14 +1,14 @@
    - +
    -

    {{application.name}} Credentials

    - +

    {{client.clientId}} Credentials

    +
    Client Secret
    @@ -18,7 +18,7 @@
    -
    +
    diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-detail.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-detail.html similarity index 76% rename from forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-detail.html rename to forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-detail.html index c3b1f9dbdb..aa3d9baa53 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-detail.html +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-detail.html @@ -1,34 +1,48 @@
    - +
    -

    {{application.name}} Application Settings

    -

    {{realm.realm}} Add Application

    +

    {{client.clientId}} Client Settings

    +

    {{realm.realm}} Add Client

    * Required fields

    - +
    - +
    - +
    - +
    - + +
    +
    + +
    + +
    + +
    +
    + +
    + +
    +
    @@ -55,7 +69,7 @@
    - +
    @@ -115,9 +129,9 @@
    - +
    - +
    @@ -139,9 +153,9 @@
    -
    +
    -
    +
    @@ -155,7 +169,7 @@
    + data-ng-class="{'input-below':client.redirectUris.length}" /> @@ -163,33 +177,33 @@
    -
    +
    + data-ng-model="client.baseUrl">
    - +
    + data-ng-model="client.adminUrl">
    - +
    + data-ng-model="client.adminUrl">
    -
    +
    -
    +
    @@ -203,7 +217,7 @@
    + data-ng-class="{'input-below':client.webOrigins.length}" /> @@ -217,41 +231,41 @@
    - +
    - +
    - +
    - +
    - +
    - +
    - +
    - +
    -
    +
    -
    +
    - +
    diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-identity-provider.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-identity-provider.html similarity index 57% rename from forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-identity-provider.html rename to forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-identity-provider.html index f4473bf8fa..c24ec4e654 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-identity-provider.html +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-identity-provider.html @@ -1,20 +1,20 @@
    - +
    -

    {{application.name}} Identity Provider Settings

    +

    {{client.clientId}} Identity Provider Settings

    {{identityProvider.identityProvider.name}} -
    - +
    +
    - +
    diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-import.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-import.html similarity index 87% rename from forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-import.html rename to forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-import.html index 4399d3c78e..1efd3be6d9 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-import.html +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-import.html @@ -1,11 +1,11 @@

    -

    {{application.name}} Application Import

    +

    {{client.clientId}} Client Import

    diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-installation.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-installation.html similarity index 73% rename from forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-installation.html rename to forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-installation.html index 5a98483923..134376ea2d 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-installation.html +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-installation.html @@ -1,14 +1,14 @@
    - +
    -

    {{application.name}} Adapter Installation

    +

    {{client.clientId}} Adapter Installation

    diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-keys.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-keys.html similarity index 92% rename from forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-keys.html rename to forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-keys.html index 1acaa54397..e789df5626 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-keys.html +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-keys.html @@ -1,13 +1,13 @@
    - +
    -

    {{application.name}} Key Pair and Certificate

    +

    {{client.clientId}} Key Pair and Certificate

    Import Keys and Cert @@ -62,7 +62,7 @@
    - Download Keys and Cert + Download Keys and Cert
    diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-list.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-list.html new file mode 100755 index 0000000000..52cf833ab4 --- /dev/null +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-list.html @@ -0,0 +1,47 @@ +
    +
    +

    +
    +

    {{realm.realm}} Clients

    +
    +
    Register node manually + tooltip-placement="bottom" href="#/register-node/realms/{{realm.realm}}/clients/{{client.id}}/clustering">Register node manually
    {{node.host}}{{node.host}} {{node.lastRegistration}}
    + + + + + + + + + + + + + + + + + + + +
    +
    + + +
    +
    + Import + Create +
    +
    Client IDEnabledBase URL
    {{client.clientId}}{{client.enabled}} + {{client.baseUrl}} + Not defined +
    No clients available
    + +
    +
    \ No newline at end of file diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-mappers-add.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-mappers-add.html similarity index 80% rename from forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-mappers-add.html rename to forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-mappers-add.html index 07ec62c626..c111c3be26 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-mappers-add.html +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-mappers-add.html @@ -1,14 +1,14 @@
    - +
    -

    {{realm.realm}} Add Builtin Protocol Mappers

    +

    {{realm.realm}} Add Builtin Protocol Mappers

    diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/oauth-client-mappers.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-mappers.html similarity index 66% rename from forms/common-themes/src/main/resources/theme/base/admin/resources/partials/oauth-client-mappers.html rename to forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-mappers.html index 83a722e7e9..343a622525 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/oauth-client-mappers.html +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-mappers.html @@ -1,13 +1,13 @@
    - +
    -

    {{realm.realm}} {{oauth.name}} {{oauth.protocol}} Protocol Mappers

    +

    {{realm.realm}} {{client.clientId}} {{client.protocol}} Protocol Mappers

    @@ -21,8 +21,8 @@ @@ -34,7 +34,7 @@ - + diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-revocation.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-revocation.html similarity index 70% rename from forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-revocation.html rename to forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-revocation.html index 41e8c11e38..22087c23ba 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-revocation.html +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-revocation.html @@ -1,13 +1,13 @@
    - +
    -

    {{application.name}} Revocation Policies

    +

    {{client.clientId}} Revocation Policies

    @@ -15,15 +15,15 @@
    - +
    -
    +
    -
    diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-role-detail.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-role-detail.html similarity index 70% rename from forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-role-detail.html rename to forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-role-detail.html index 5145f37b39..d57ab3f99b 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-role-detail.html +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-role-detail.html @@ -1,26 +1,26 @@
    - +
    -

    {{application.name}} {{role.name}} Application Role

    -

    {{application.name}} Add Application Role

    +

    {{client.clientId}} {{role.name}} Client Role

    +

    {{client.clientId}} Add Client Role

    * Required fields

    -
    +
    @@ -81,56 +81,56 @@
    -
    - Composite Application Roles +
    + Composite Client Roles
    - +
    - +
    -
    -
    +
    +
    - - + ng-model="selectedClientRoles" + ng-options="r.name for r in clientRoles">
    - -
    - - + ng-model="selectedClientMappings" + ng-options="r.name for r in clientMappings">
    -
    +
    -
    +
    diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-role-list.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-role-list.html similarity index 78% rename from forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-role-list.html rename to forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-role-list.html index e10126efd8..f996169d89 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-role-list.html +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-role-list.html @@ -1,20 +1,20 @@
    - +
    -

    {{application.name}} Application Roles

    +

    {{client.clientId}} Client Roles

    {{mapper.name}}{{mapper.name}} {{mapperTypes[mapper.protocolMapper].category}} {{mapperTypes[mapper.protocolMapper].name}}
    - @@ -52,12 +52,12 @@ --> - + - +
    +
    {{role.name}}{{role.name}} {{role.composite}} {{role.description}}
    No application roles availableNo client roles available
    diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-saml-key-export.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-saml-key-export.html similarity index 85% rename from forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-saml-key-export.html rename to forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-saml-key-export.html index 2431612060..1f29c0543e 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-saml-key-export.html +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-saml-key-export.html @@ -1,14 +1,14 @@
    - +
    -

    {{application.name}} SAML {{keyType}} Key Export

    +

    {{client.clientId}} SAML {{keyType}} Key Export

    diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-saml-key-import.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-saml-key-import.html similarity index 85% rename from forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-saml-key-import.html rename to forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-saml-key-import.html index 63e5a968d7..3a26937fd7 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-saml-key-import.html +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-saml-key-import.html @@ -1,14 +1,14 @@
    - +
    -

    {{application.name}} SAML {{keyType}} Key Import

    +

    {{client.clientId}} SAML {{keyType}} Key Import

    diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-saml-keys.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-saml-keys.html similarity index 86% rename from forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-saml-keys.html rename to forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-saml-keys.html index 5d9ba63782..206ce66366 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-saml-keys.html +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-saml-keys.html @@ -1,15 +1,15 @@
    - +
    -

    {{application.name}} SAML Keys

    +

    {{client.clientId}} SAML Keys

    -
    +
    Signing Key
    @@ -35,7 +35,7 @@
    -
    +
    Encryption Key
    diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-scope-mappings.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-scope-mappings.html similarity index 66% rename from forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-scope-mappings.html rename to forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-scope-mappings.html index 852f1f4116..6339f4efc7 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-scope-mappings.html +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-scope-mappings.html @@ -1,28 +1,28 @@
    - +
    -

    {{application.name}} Scope Mappings

    +

    {{client.clientId}} Scope Mappings

    - +
    - +
    -
    +
    Realm Roles
    @@ -66,56 +66,56 @@
    -
    - Application Roles +
    + Client Roles
    - +
    - +
    -
    +
    - - + ng-model="selectedClientRoles" + ng-options="r.name for r in clientRoles">
    - -
    - - + ng-model="selectedClientMappings" + ng-options="r.name for r in clientMappings">
    -
    - - + ng-options="r.name for r in clientComposite">
    diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-sessions.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-sessions.html similarity index 78% rename from forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-sessions.html rename to forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-sessions.html index 3284c3ac5f..2df97f6108 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-sessions.html +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-sessions.html @@ -1,13 +1,13 @@
    - +
    -

    {{application.name}} Active Sessions

    +

    {{client.clientId}} Active Sessions

    @@ -15,7 +15,7 @@
    - +
    diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/oauth-client-claims.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/oauth-client-claims.html deleted file mode 100755 index f3302260c2..0000000000 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/oauth-client-claims.html +++ /dev/null @@ -1,19 +0,0 @@ -
    -
    - -
    - -

    {{oauth.name}} Allowed Claims

    -
    -
    -
    - - -
    -
    -
    -
    diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/oauth-client-credentials.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/oauth-client-credentials.html deleted file mode 100755 index 9b5db3433f..0000000000 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/oauth-client-credentials.html +++ /dev/null @@ -1,29 +0,0 @@ -
    -
    - -
    - -

    {{oauth.name}} Credentials

    -
    -
    - Client Secret -
    - -
    - -
    -
    -
    -
    - -
    -
    -
    -
    - diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/oauth-client-detail.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/oauth-client-detail.html deleted file mode 100755 index 46daf9fc06..0000000000 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/oauth-client-detail.html +++ /dev/null @@ -1,116 +0,0 @@ -
    -
    - -
    - - -

    {{realm.realm}} Add OAuth Client

    -

    * Required fields

    -

    {{oauth.name}} Settings

    -
    -
    - -
    - -
    - -
    -
    - -
    - -
    - -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    - -
    - -
    -
    - -
    -
    - - - - -
    -
    -
    -
    - - - - -
    -
    - -
    -
    - -
    -
    - - - - -
    -
    -
    -
    - - - - -
    -
    - -
    -
    - -
    - - -
    -
    - - - -
    -
    -
    -
    \ No newline at end of file diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/oauth-client-identity-provider.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/oauth-client-identity-provider.html deleted file mode 100755 index 619ce331ea..0000000000 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/oauth-client-identity-provider.html +++ /dev/null @@ -1,31 +0,0 @@ -
    -
    - -
    - -

    {{oauth.name}} Identity Provider Settings

    -
    -
    - {{identityProvider.identityProvider.name}} - -
    - -
    -
    - -
    - -
    -
    -
    -
    - - -
    -
    -
    -
    diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/oauth-client-installation.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/oauth-client-installation.html deleted file mode 100755 index 5a8cd4f940..0000000000 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/oauth-client-installation.html +++ /dev/null @@ -1,26 +0,0 @@ -
    -
    - -
    - -

    {{oauth.name}} Adapter Installation

    -
    -
    -
    -
    - -
    -
    -
    -
    - -
    - Download -
    - -
    -
    \ No newline at end of file diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/oauth-client-list.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/oauth-client-list.html deleted file mode 100755 index ebf59a4622..0000000000 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/oauth-client-list.html +++ /dev/null @@ -1,55 +0,0 @@ -
    -
    -

    -
    -

    {{realm.realm}} OAuth Clients

    - - - - - - - - - - - - - - - - - - - - -
    -
    - - -
    - -
    OAuth Client NameEnabled
    {{client.name}}{{client.enabled}}
    No clients available
    - -
    -
    diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/oauth-client-mappers-add.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/oauth-client-mappers-add.html deleted file mode 100755 index 0b0284e060..0000000000 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/oauth-client-mappers-add.html +++ /dev/null @@ -1,49 +0,0 @@ -
    -
    - -
    - -

    Add Builtin Protocol Mappers

    - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - -
    -
    - -
    -
    NameCategoryTypeAdd
    {{mapper.name}}{{mapperTypes[mapper.protocolMapper].category}}{{mapperTypes[mapper.protocolMapper].name}}
    No mappers available
    -
    -
    diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/oauth-client-protocol-mapper-detail.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/oauth-client-protocol-mapper-detail.html deleted file mode 100755 index 36738b65b6..0000000000 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/oauth-client-protocol-mapper-detail.html +++ /dev/null @@ -1,108 +0,0 @@ -
    -
    - -
    - - - -

    {{mapper.name}} Protocol Mapper

    -

    Create Protocol Mapper

    -

    * Required fields

    -
    - -
    -
    - -
    - -
    - -
    -
    - -
    - -
    -
    -
    - -
    - -
    - -
    -
    - -
    - -
    - -
    -
    - - -
    - -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    - -
    - -
    -
    - - -
    - -
    -
    - -
    -
    - -
    - -
    - -
    -
    - - -
    - -
    - - - -
    -
    -
    -
    \ No newline at end of file diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/oauth-client-revocation.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/oauth-client-revocation.html deleted file mode 100755 index 1af3cafa1b..0000000000 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/oauth-client-revocation.html +++ /dev/null @@ -1,29 +0,0 @@ -
    -
    - -
    - -

    {{oauth.name}} Revocation Policies

    -
    -
    -
    - -
    - -
    - -
    -
    -
    - - -
    -
    -
    -
    diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/oauth-client-scope-mappings.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/oauth-client-scope-mappings.html deleted file mode 100755 index f137b5db37..0000000000 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/oauth-client-scope-mappings.html +++ /dev/null @@ -1,124 +0,0 @@ -
    -
    - -
    - -

    {{oauth.name}} Scope Mappings

    -

    -
    -
    -
    - -
    - -
    - -
    -
    -
    -
    -
    - Realm Roles -
    -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    -
    -
    - -
    - Application Roles -
    - -
    -
    -
    - -
    -
    -
    - -
    -
    -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    -
    -
    -
    -
    -
    \ No newline at end of file diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/protocol-mapper-detail.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/protocol-mapper-detail.html index aed7f506c6..03a52bb85e 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/protocol-mapper-detail.html +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/protocol-mapper-detail.html @@ -1,18 +1,18 @@
    - +

    {{mapper.name}} Protocol Mapper

    diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-cache-settings.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-cache-settings.html index 2567173017..e4a134c17d 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-cache-settings.html +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-cache-settings.html @@ -12,7 +12,7 @@
    - +
    diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-default-roles.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-default-roles.html index d2207f732d..f03349ea82 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-default-roles.html +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-default-roles.html @@ -40,45 +40,45 @@
    -
    - Application Default Roles +
    + Client Default Roles
    - +
    - +
    -
    +
    - - + ng-model="selectedClientRoles" + ng-options="r for r in availableClientRoles">
    - -
    - - + ng-model="selectedClientDefRoles" + ng-options="r for r in client.defaultRoles">
    diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-detail.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-detail.html index 80f8e13a7d..ae5b53a0a5 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-detail.html +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-detail.html @@ -17,7 +17,7 @@
    - +
    diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-oidc.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-oidc.html index 7bf40354a3..67b0a68fe1 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-oidc.html +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-oidc.html @@ -55,6 +55,13 @@
    +
    + +
    + +
    + +
    OpenID Connect Config @@ -91,7 +98,7 @@
    - +
    @@ -101,7 +108,7 @@ Show Secret Hide Secret
    - +
    diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-saml.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-saml.html index 10327e6c5f..3e151fd75d 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-saml.html +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-saml.html @@ -55,6 +55,13 @@
    +
    + +
    + +
    + +
    SAML Config diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-social.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-social.html index 0a8b56a5c6..dd0709392a 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-social.html +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-social.html @@ -25,7 +25,7 @@
    - +
    @@ -35,7 +35,7 @@ Show Secret Hide Secret
    - +
    @@ -73,6 +73,13 @@
    +
    + +
    + +
    + +
    diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-stackoverflow-ext.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-stackoverflow-ext.html index 86516dfaaa..07a0e604e1 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-stackoverflow-ext.html +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-stackoverflow-ext.html @@ -3,5 +3,5 @@
    - +
    diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider.html index 1c0ed54a06..778bb2c889 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider.html +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider.html @@ -12,7 +12,7 @@ Table of identity providers - +
    - +
    @@ -98,4 +98,4 @@
    -
    \ No newline at end of file +
    diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-tokens.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-tokens.html index 2f30127aef..eb519ee9b3 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-tokens.html +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-tokens.html @@ -90,8 +90,7 @@
    - - +
    diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/role-detail.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/role-detail.html index d5be190d09..412c8a09ba 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/role-detail.html +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/role-detail.html @@ -74,45 +74,45 @@
    -
    - Composite Application Roles +
    + Composite Client Roles
    -
    -
    +
    - - + ng-model="selectedClientRoles" + ng-options="r.name for r in clientRoles">
    - -
    - - + ng-model="selectedClientMappings" + ng-options="r.name for r in clientMappings">
    diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/role-mappings.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/role-mappings.html index 0ae08be374..314212bd29 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/role-mappings.html +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/role-mappings.html @@ -63,56 +63,56 @@
    -
    - Application Roles +
    + Client Roles
    - +
    - +
    -
    +
    - - + ng-model="selectedClientRoles" + ng-options="r.name for r in clientRoles">
    - -
    - - + ng-model="selectedClientMappings" + ng-options="r.name for r in clientMappings">
    -
    - - + ng-options="r.name for r in clientComposite">
    diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/session-realm.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/session-realm.html index 1394703e15..2535b46f26 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/session-realm.html +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/session-realm.html @@ -18,13 +18,13 @@ - Application + Client Active Sessions - {{data.name}} + {{data.clientId}} {{data.active}} diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/session-revocation.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/session-revocation.html index c87af7f9ae..f84c5ae914 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/session-revocation.html +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/session-revocation.html @@ -18,12 +18,12 @@
    -
    +
    -
    diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/user-sessions.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/user-sessions.html index f3de7e404d..9db3f7de09 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/user-sessions.html +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/user-sessions.html @@ -27,8 +27,7 @@ IP Address Started Last Access - Applications - OAuth Clients + Clients Action @@ -38,16 +37,11 @@ {{session.start | date:'medium'}} {{session.lastAccess | date:'medium'}} -
    - {{name}} + - - - logout diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/templates/kc-navigation-application.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/templates/kc-navigation-application.html deleted file mode 100755 index 49949d9c60..0000000000 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/templates/kc-navigation-application.html +++ /dev/null @@ -1,13 +0,0 @@ - \ No newline at end of file diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/templates/kc-navigation-client.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/templates/kc-navigation-client.html new file mode 100755 index 0000000000..9794e388f3 --- /dev/null +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/templates/kc-navigation-client.html @@ -0,0 +1,13 @@ + \ No newline at end of file diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/templates/kc-navigation-oauth-client.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/templates/kc-navigation-oauth-client.html deleted file mode 100755 index 78c7ac98ce..0000000000 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/templates/kc-navigation-oauth-client.html +++ /dev/null @@ -1,9 +0,0 @@ - \ No newline at end of file diff --git a/forms/common-themes/src/main/resources/theme/base/login/login.ftl b/forms/common-themes/src/main/resources/theme/base/login/login.ftl index 505e1853e1..858e0751c9 100755 --- a/forms/common-themes/src/main/resources/theme/base/login/login.ftl +++ b/forms/common-themes/src/main/resources/theme/base/login/login.ftl @@ -1,17 +1,9 @@ <#import "template.ftl" as layout> <@layout.registrationLayout displayInfo=social.displayInfo; section> <#if section = "title"> - <#if client.application> - ${msg("loginTitle",(realm.name!''))} - <#elseif client.oauthClient> - ${msg("loginOauthTitle",(realm.name!''))} - + ${msg("loginTitle",(realm.name!''))} <#elseif section = "header"> - <#if client.application> - ${msg("loginTitleHtml",(realm.name!''))} - <#elseif client.oauthClient> - ${msg("loginOauthTitleHtml",(realm.name!''), (client.clientId!''))} - + ${msg("loginTitleHtml",(realm.name!''))} <#elseif section = "form"> <#if realm.password>
    diff --git a/forms/common-themes/src/main/resources/theme/base/login/messages/messages_de.properties b/forms/common-themes/src/main/resources/theme/base/login/messages/messages_de.properties index 06abbb1d26..75ffd3ee9b 100644 --- a/forms/common-themes/src/main/resources/theme/base/login/messages/messages_de.properties +++ b/forms/common-themes/src/main/resources/theme/base/login/messages/messages_de.properties @@ -11,7 +11,7 @@ registerWithTitle=Registrierung bei {0} registerWithTitleHtml=Registrierung bei {0} loginTitle=Anmeldung bei {0} loginTitleHtml=Anmeldung bei {0} -loginOauthTitle=Tempor\u00E4rer zugriff auf {0} +loginOauthTitle= loginOauthTitleHtml=Tempor\u00E4rer zugriff auf {0} angefordert von {1}. loginTotpTitle=Mobile Authentifizierung Einrichten loginProfileTitle=Benutzerkonto Informationen aktualisieren diff --git a/forms/common-themes/src/main/resources/theme/base/login/messages/messages_en.properties b/forms/common-themes/src/main/resources/theme/base/login/messages/messages_en.properties index 4bb3a66ea2..7c1347f389 100755 --- a/forms/common-themes/src/main/resources/theme/base/login/messages/messages_en.properties +++ b/forms/common-themes/src/main/resources/theme/base/login/messages/messages_en.properties @@ -11,8 +11,6 @@ registerWithTitle=Register with {0} registerWithTitleHtml=Register with {0} loginTitle=Log in to {0} loginTitleHtml=Log in to {0} -loginOauthTitle=Temporary access for {0} -loginOauthTitleHtml=Temporary access for {0} requested by {1}. loginTotpTitle=Mobile Authenticator Setup loginProfileTitle=Update Account Information oauthGrantTitle=OAuth Grant diff --git a/forms/login-freemarker/pom.xml b/forms/login-freemarker/pom.xml index e83bc52177..c5b7134db4 100755 --- a/forms/login-freemarker/pom.xml +++ b/forms/login-freemarker/pom.xml @@ -71,6 +71,12 @@ jboss-logging provided + + + junit + junit + test + diff --git a/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/FreeMarkerLoginFormsProvider.java b/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/FreeMarkerLoginFormsProvider.java index 0dd6342adb..228a1466cd 100755 --- a/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/FreeMarkerLoginFormsProvider.java +++ b/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/FreeMarkerLoginFormsProvider.java @@ -1,23 +1,5 @@ package org.keycloak.login.freemarker; -import java.io.IOException; -import java.net.URI; -import java.text.MessageFormat; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Properties; -import java.util.concurrent.TimeUnit; - -import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.MultivaluedMap; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.UriBuilder; -import javax.ws.rs.core.UriInfo; - import org.jboss.logging.Logger; import org.jboss.resteasy.specimpl.MultivaluedMapImpl; import org.keycloak.OAuth2Constants; @@ -57,6 +39,23 @@ import org.keycloak.models.utils.FormMessage; import org.keycloak.services.messages.Messages; import org.keycloak.services.resources.flows.Urls; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriBuilder; +import javax.ws.rs.core.UriInfo; +import java.io.IOException; +import java.net.URI; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Properties; +import java.util.concurrent.TimeUnit; + /** * @author Stian Thorgersen */ diff --git a/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/ClientBean.java b/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/ClientBean.java index fcd9e1136c..53f7937106 100755 --- a/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/ClientBean.java +++ b/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/ClientBean.java @@ -1,37 +1,25 @@ package org.keycloak.login.freemarker.model; -import org.keycloak.models.ApplicationModel; import org.keycloak.models.ClientModel; -import org.keycloak.models.OAuthClientModel; /** * @author Bill Burke * @version $Revision: 1 $ */ public class ClientBean { + protected ClientModel client; public ClientBean(ClientModel client) { this.client = client; } - public boolean isApplication() { - return client instanceof ApplicationModel; - } - - public boolean isOauthClient() { - return client instanceof OAuthClientModel; - } - public String getClientId() { return client.getClientId(); } public String getBaseUrl() { - if (client instanceof ApplicationModel) { - return ((ApplicationModel) client).getBaseUrl(); - } - return null; + return client.getBaseUrl(); } } diff --git a/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/IdentityProviderBean.java b/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/IdentityProviderBean.java index 8da7f4da40..65e02723c7 100755 --- a/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/IdentityProviderBean.java +++ b/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/IdentityProviderBean.java @@ -21,21 +21,21 @@ */ package org.keycloak.login.freemarker.model; -import org.keycloak.OAuth2Constants; -import org.keycloak.models.ApplicationModel; -import org.keycloak.models.ClientModel; -import org.keycloak.models.Constants; import org.keycloak.models.IdentityProviderModel; import org.keycloak.models.RealmModel; import org.keycloak.services.resources.flows.Urls; import javax.ws.rs.core.UriInfo; import java.net.URI; +import java.util.Comparator; import java.util.LinkedList; import java.util.List; +import java.util.Set; +import java.util.TreeSet; /** * @author Stian Thorgersen + * @author Vlastimil Elias (velias at redhat dot com) */ public class IdentityProviderBean { @@ -49,23 +49,24 @@ public class IdentityProviderBean { List identityProviders = realm.getIdentityProviders(); if (!identityProviders.isEmpty()) { - providers = new LinkedList(); - + Set orderedSet = new TreeSet<>(IdentityProviderComparator.INSTANCE); for (IdentityProviderModel identityProvider : identityProviders) { if (identityProvider.isEnabled()) { - addIdentityProvider(realm, baseURI, identityProvider); + addIdentityProvider(orderedSet, realm, baseURI, identityProvider); } } - if (!providers.isEmpty()) { + if (!orderedSet.isEmpty()) { + providers = new LinkedList(orderedSet); displaySocial = true; } } } - private void addIdentityProvider(RealmModel realm, URI baseURI, IdentityProviderModel identityProvider) { + private void addIdentityProvider(Set orderedSet, RealmModel realm, URI baseURI, IdentityProviderModel identityProvider) { String loginUrl = Urls.identityProviderAuthnRequest(baseURI, identityProvider.getAlias(), realm.getName()).toString(); - providers.add(new IdentityProvider(identityProvider.getAlias(), identityProvider.getProviderId(), loginUrl)); + orderedSet.add(new IdentityProvider(identityProvider.getAlias(), identityProvider.getProviderId(), loginUrl, + identityProvider.getConfig() != null ? identityProvider.getConfig().get("guiOrder") : null)); } public List getProviders() { @@ -81,12 +82,13 @@ public class IdentityProviderBean { private final String alias; private final String providerId; // This refer to providerType (facebook, google, etc.) private final String loginUrl; + private final String guiOrder; - public IdentityProvider(String alias, String providerId,String loginUrl) { + public IdentityProvider(String alias, String providerId, String loginUrl, String guiOrder) { this.alias = alias; this.providerId = providerId; - this.loginUrl = loginUrl; + this.guiOrder = guiOrder; } public String getAlias() { @@ -100,5 +102,44 @@ public class IdentityProviderBean { public String getProviderId() { return providerId; } + + public String getGuiOrder() { + return guiOrder; + } + } + + public static class IdentityProviderComparator implements Comparator { + + public static IdentityProviderComparator INSTANCE = new IdentityProviderComparator(); + + private IdentityProviderComparator() { + + } + + @Override + public int compare(IdentityProvider o1, IdentityProvider o2) { + + int o1order = parseOrder(o1); + int o2order = parseOrder(o2); + + if (o1order > o2order) + return 1; + else if (o1order < o2order) + return -1; + + return 1; + } + + private int parseOrder(IdentityProvider ip) { + if (ip != null && ip.getGuiOrder() != null) { + try { + return Integer.parseInt(ip.getGuiOrder()); + } catch (NumberFormatException e) { + // ignore it and use defaulr + } + } + return 10000; + } + } } diff --git a/forms/login-freemarker/src/test/java/org/keycloak/login/freemarker/model/IdentityProviderBeanTest.java b/forms/login-freemarker/src/test/java/org/keycloak/login/freemarker/model/IdentityProviderBeanTest.java new file mode 100644 index 0000000000..dda3316a13 --- /dev/null +++ b/forms/login-freemarker/src/test/java/org/keycloak/login/freemarker/model/IdentityProviderBeanTest.java @@ -0,0 +1,55 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @authors tag. All rights reserved. + */ +package org.keycloak.login.freemarker.model; + +import org.junit.Assert; +import org.junit.Test; +import org.keycloak.login.freemarker.model.IdentityProviderBean.IdentityProvider; +import org.keycloak.login.freemarker.model.IdentityProviderBean.IdentityProviderComparator; + +/** + * Unit test for {@link IdentityProviderBean} + * + * @author Vlastimil Elias (velias at redhat dot com) + */ +public class IdentityProviderBeanTest { + + + @Test + public void testIdentityProviderComparator() { + + IdentityProvider o1 = new IdentityProvider("alias1", "id1", "ur1", null); + IdentityProvider o2 = new IdentityProvider("alias2", "id2", "ur2", null); + + // guiOrder not defined at any object - first is always lower + Assert.assertEquals(1, IdentityProviderComparator.INSTANCE.compare(o1, o2)); + Assert.assertEquals(1, IdentityProviderComparator.INSTANCE.compare(o2, o1)); + + // guiOrder is not a number so it is same as not defined - first is always lower + o1 = new IdentityProvider("alias1", "id1", "ur1", "not a number"); + Assert.assertEquals(1, IdentityProviderComparator.INSTANCE.compare(o1, o2)); + Assert.assertEquals(1, IdentityProviderComparator.INSTANCE.compare(o2, o1)); + + // guiOrder is defined for one only to it is always first + o1 = new IdentityProvider("alias1", "id1", "ur1", "0"); + Assert.assertEquals(-1, IdentityProviderComparator.INSTANCE.compare(o1, o2)); + Assert.assertEquals(1, IdentityProviderComparator.INSTANCE.compare(o2, o1)); + + // guiOrder is defined for both but is same - first is always lower + o1 = new IdentityProvider("alias1", "id1", "ur1", "0"); + o2 = new IdentityProvider("alias2", "id2", "ur2", "0"); + Assert.assertEquals(1, IdentityProviderComparator.INSTANCE.compare(o1, o2)); + Assert.assertEquals(1, IdentityProviderComparator.INSTANCE.compare(o2, o1)); + + // guiOrder is reflected + o1 = new IdentityProvider("alias1", "id1", "ur1", "0"); + o2 = new IdentityProvider("alias2", "id2", "ur2", "1"); + Assert.assertEquals(-1, IdentityProviderComparator.INSTANCE.compare(o1, o2)); + Assert.assertEquals(1, IdentityProviderComparator.INSTANCE.compare(o2, o1)); + + } + +} diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/ServerRequest.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/ServerRequest.java index 27a2949520..701dc097f4 100755 --- a/integration/adapter-core/src/main/java/org/keycloak/adapters/ServerRequest.java +++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/ServerRequest.java @@ -102,8 +102,8 @@ public class ServerRequest { formparams.add(new BasicNameValuePair(OAuth2Constants.CODE, code)); formparams.add(new BasicNameValuePair(OAuth2Constants.REDIRECT_URI, redirectUri)); if (sessionId != null) { - formparams.add(new BasicNameValuePair(AdapterConstants.APPLICATION_SESSION_STATE, sessionId)); - formparams.add(new BasicNameValuePair(AdapterConstants.APPLICATION_SESSION_HOST, HostUtils.getHostName())); + formparams.add(new BasicNameValuePair(AdapterConstants.CLIENT_SESSION_STATE, sessionId)); + formparams.add(new BasicNameValuePair(AdapterConstants.CLIENT_SESSION_HOST, HostUtils.getHostName())); } HttpResponse response = null; HttpPost post = new HttpPost(tokenUrl); @@ -237,7 +237,7 @@ public class ServerRequest { } List formparams = new ArrayList(); - formparams.add(new BasicNameValuePair(AdapterConstants.APPLICATION_CLUSTER_HOST, host)); + formparams.add(new BasicNameValuePair(AdapterConstants.CLIENT_CLUSTER_HOST, host)); HttpPost post = new HttpPost(endpointUrl); diff --git a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ApplicationResource.java b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ClientResource.java similarity index 91% rename from integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ApplicationResource.java rename to integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ClientResource.java index 2601d5328a..94b254d75d 100755 --- a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ApplicationResource.java +++ b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ClientResource.java @@ -1,6 +1,6 @@ package org.keycloak.admin.client.resource; -import org.keycloak.representations.idm.ApplicationRepresentation; +import org.keycloak.representations.idm.ClientRepresentation; import org.keycloak.representations.idm.CredentialRepresentation; import org.keycloak.representations.idm.UserSessionRepresentation; @@ -21,18 +21,18 @@ import java.util.Set; /** * @author rodrigo.sasaki@icarros.com.br */ -public interface ApplicationResource { +public interface ClientResource { @Path("protocol-mappers") public ProtocolMappersResource getProtocolMappers(); @GET @Produces(MediaType.APPLICATION_JSON) - public ApplicationRepresentation toRepresentation(); + public ClientRepresentation toRepresentation(); @PUT @Consumes(MediaType.APPLICATION_JSON) - public void update(ApplicationRepresentation applicationRepresentation); + public void update(ClientRepresentation clientRepresentation); @DELETE public void remove(); diff --git a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ApplicationsResource.java b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ClientsResource.java similarity index 56% rename from integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ApplicationsResource.java rename to integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ClientsResource.java index 6ccbdd8643..9843bc53cf 100755 --- a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ApplicationsResource.java +++ b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ClientsResource.java @@ -1,6 +1,6 @@ package org.keycloak.admin.client.resource; -import org.keycloak.representations.idm.ApplicationRepresentation; +import org.keycloak.representations.idm.ClientRepresentation; import javax.ws.rs.Consumes; import javax.ws.rs.GET; @@ -14,18 +14,18 @@ import java.util.List; /** * @author rodrigo.sasaki@icarros.com.br */ -public interface ApplicationsResource { +public interface ClientsResource { - @Path("{appName}") - public ApplicationResource get(@PathParam("appName") String appName); + @Path("{clientId}") + public ClientResource get(@PathParam("clientId") String clientId); @POST @Consumes(MediaType.APPLICATION_JSON) - public void create(ApplicationRepresentation applicationRepresentation); + public void create(ClientRepresentation clientRepresentation); @GET @Produces(MediaType.APPLICATION_JSON) - public List findAll(); + public List findAll(); diff --git a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/OAuthClientResource.java b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/OAuthClientResource.java deleted file mode 100755 index a2effee406..0000000000 --- a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/OAuthClientResource.java +++ /dev/null @@ -1,57 +0,0 @@ -package org.keycloak.admin.client.resource; - -import org.keycloak.representations.idm.CredentialRepresentation; -import org.keycloak.representations.idm.OAuthClientRepresentation; - -import javax.ws.rs.Consumes; -import javax.ws.rs.DELETE; -import javax.ws.rs.GET; -import javax.ws.rs.POST; -import javax.ws.rs.PUT; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; -import javax.ws.rs.core.MediaType; - -/** - * @author rodrigo.sasaki@icarros.com.br - */ -public interface OAuthClientResource { - - @Path("protocol-mappers") - public ProtocolMappersResource getProtocolMappers(); - - // TODO - // @Path("certificates/{attr}") - // public ClientAttributeCertificateResource getCertficateResource(@PathParam("attr") String attributePrefix); - - @GET - @Produces(MediaType.APPLICATION_JSON) - public OAuthClientRepresentation toRepresentation(); - - @PUT - @Consumes(MediaType.APPLICATION_JSON) - public void update(OAuthClientRepresentation oAuthClientRepresentation); - - @DELETE - public void remove(); - - @POST - @Path("client-secret") - @Consumes("application/json") - @Produces(MediaType.APPLICATION_JSON) - public CredentialRepresentation generateNewSecret(); - - @GET - @Path("client-secret") - @Produces(MediaType.APPLICATION_JSON) - public CredentialRepresentation getSecret(); - - @GET - @Path("installation") - @Produces(MediaType.APPLICATION_JSON) - public String getInstallationJson(); - - @Path("/scope-mappings") - public RoleMappingResource getScopeMappings(); - -} diff --git a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/OAuthClientsResource.java b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/OAuthClientsResource.java deleted file mode 100755 index 027c82923c..0000000000 --- a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/OAuthClientsResource.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.keycloak.admin.client.resource; - -import org.keycloak.representations.idm.OAuthClientRepresentation; - -import javax.ws.rs.Consumes; -import javax.ws.rs.GET; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.core.MediaType; -import java.util.List; - -/** - * @author rodrigo.sasaki@icarros.com.br - */ -public interface OAuthClientsResource { - - @GET - @Produces(MediaType.APPLICATION_JSON) - public List findAll(); - - @POST - @Consumes(MediaType.APPLICATION_JSON) - public void create(OAuthClientRepresentation oAuthClientRepresentation); - - @Path("{oAuthClientId}") - public OAuthClientResource get(@PathParam("oAuthClientId") String oAuthClientId); - -} diff --git a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/RealmResource.java b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/RealmResource.java index 1ed0a8055b..4045ecfe69 100644 --- a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/RealmResource.java +++ b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/RealmResource.java @@ -23,15 +23,12 @@ public interface RealmResource { @Consumes(MediaType.APPLICATION_JSON) public void update(RealmRepresentation realmRepresentation); - @Path("applications") - public ApplicationsResource applications(); + @Path("clients") + public ClientsResource clients(); @Path("users") public UsersResource users(); - @Path("oauth-clients") - public OAuthClientsResource oAuthClients(); - @Path("roles") public RolesResource roles(); diff --git a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/CredentialAddHandler.java b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/CredentialAddHandler.java index c3c37fa63c..17f7928198 100755 --- a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/CredentialAddHandler.java +++ b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/CredentialAddHandler.java @@ -40,7 +40,7 @@ public class CredentialAddHandler extends AbstractAddStepHandler { @Override protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model, ServiceVerificationHandler verificationHandler, List> newControllers) throws OperationFailedException { - KeycloakAdapterConfigService ckService = KeycloakAdapterConfigService.find(context); + KeycloakAdapterConfigService ckService = KeycloakAdapterConfigService.getInstance(); ckService.addCredential(operation, context.resolveExpressions(model)); } diff --git a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/CredentialReadWriteAttributeHandler.java b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/CredentialReadWriteAttributeHandler.java index 6289ff4539..75b334d3dd 100644 --- a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/CredentialReadWriteAttributeHandler.java +++ b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/CredentialReadWriteAttributeHandler.java @@ -33,7 +33,7 @@ public class CredentialReadWriteAttributeHandler extends AbstractWriteAttributeH protected boolean applyUpdateToRuntime(OperationContext context, ModelNode operation, String attributeName, ModelNode resolvedValue, ModelNode currentValue, AbstractWriteAttributeHandler.HandbackHolder hh) throws OperationFailedException { - KeycloakAdapterConfigService ckService = KeycloakAdapterConfigService.find(context); + KeycloakAdapterConfigService ckService = KeycloakAdapterConfigService.getInstance(); ckService.updateCredential(operation, attributeName, resolvedValue); hh.setHandback(ckService); diff --git a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/CredentialRemoveHandler.java b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/CredentialRemoveHandler.java index 1cad10bfb0..0023d41cc1 100644 --- a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/CredentialRemoveHandler.java +++ b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/CredentialRemoveHandler.java @@ -35,7 +35,7 @@ public final class CredentialRemoveHandler extends AbstractRemoveStepHandler { @Override protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model) throws OperationFailedException { - KeycloakAdapterConfigService ckService = KeycloakAdapterConfigService.find(context); + KeycloakAdapterConfigService ckService = KeycloakAdapterConfigService.getInstance(); ckService.removeCredential(operation); } diff --git a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakAdapterConfigDeploymentProcessor.java b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakAdapterConfigDeploymentProcessor.java index f96d1c2c99..bebf6dbe54 100755 --- a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakAdapterConfigDeploymentProcessor.java +++ b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakAdapterConfigDeploymentProcessor.java @@ -68,8 +68,7 @@ public class KeycloakAdapterConfigDeploymentProcessor implements DeploymentUnitP DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit(); String deploymentName = deploymentUnit.getName(); - KeycloakAdapterConfigService service = KeycloakAdapterConfigService.find(phaseContext.getServiceRegistry()); - //log.info("********* CHECK KEYCLOAK DEPLOYMENT: " + deploymentName); + KeycloakAdapterConfigService service = KeycloakAdapterConfigService.getInstance(); if (service.isSecureDeployment(deploymentName)) { addKeycloakAuthData(phaseContext, deploymentName, service); } diff --git a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakAdapterConfigDeploymentProcessorEAP6.java b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakAdapterConfigDeploymentProcessorEAP6.java index 77261ba311..dc2d8e76d0 100755 --- a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakAdapterConfigDeploymentProcessorEAP6.java +++ b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakAdapterConfigDeploymentProcessorEAP6.java @@ -50,7 +50,7 @@ public class KeycloakAdapterConfigDeploymentProcessorEAP6 implements DeploymentU DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit(); String deploymentName = deploymentUnit.getName(); - KeycloakAdapterConfigService service = KeycloakAdapterConfigService.find(phaseContext.getServiceRegistry()); + KeycloakAdapterConfigService service = KeycloakAdapterConfigService.getInstance(); //log.info("********* CHECK KEYCLOAK DEPLOYMENT: " + deploymentName); if (service.isSecureDeployment(deploymentName)) { addKeycloakAuthData(phaseContext, deploymentName, service); diff --git a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakAdapterConfigService.java b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakAdapterConfigService.java index d860cb65c4..81bb610138 100755 --- a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakAdapterConfigService.java +++ b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakAdapterConfigService.java @@ -17,17 +17,9 @@ package org.keycloak.subsystem.extension; -import org.jboss.as.controller.OperationContext; import org.jboss.dmr.ModelNode; import org.jboss.dmr.Property; import org.jboss.logging.Logger; -import org.jboss.msc.service.Service; -import org.jboss.msc.service.ServiceController; -import org.jboss.msc.service.ServiceName; -import org.jboss.msc.service.ServiceRegistry; -import org.jboss.msc.service.StartContext; -import org.jboss.msc.service.StartException; -import org.jboss.msc.service.StopContext; import java.util.HashMap; import java.util.Map; @@ -40,41 +32,27 @@ import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ADD * * @author Stan Silvert ssilvert@redhat.com (C) 2013 Red Hat Inc. */ -public final class KeycloakAdapterConfigService implements Service { +public final class KeycloakAdapterConfigService { protected Logger log = Logger.getLogger(KeycloakAdapterConfigService.class); private static final String CREDENTIALS_JSON_NAME = "credentials"; - // Right now this is used as a service, but I'm not sure it really needs to be implemented that way. - // It's also a singleton serving the entire subsystem, but the INSTANCE variable is currently only - // used during initialization of the subsystem. - public static final ServiceName SERVICE_NAME = ServiceName.JBOSS.append("KeycloakAdapterConfigService"); - public static final KeycloakAdapterConfigService INSTANCE = new KeycloakAdapterConfigService(); + private static final KeycloakAdapterConfigService INSTANCE = new KeycloakAdapterConfigService(); - private Map realms = new HashMap(); + public static KeycloakAdapterConfigService getInstance() { + return INSTANCE; + } + + private final Map realms = new HashMap(); // keycloak-secured deployments - private Map secureDeployments = new HashMap(); + private final Map secureDeployments = new HashMap(); // key=auth-server deployment name; value=web-context - private Map webContexts = new HashMap(); + private final Map webContexts = new HashMap(); + + private KeycloakAdapterConfigService() { - - } - - @Override - public void start(StartContext sc) throws StartException { - - } - - @Override - public void stop(StopContext sc) { - - } - - @Override - public KeycloakAdapterConfigService getValue() throws IllegalStateException, IllegalArgumentException { - return this; } public void addServerDeployment(String deploymentName, String webContext) { @@ -223,17 +201,4 @@ public final class KeycloakAdapterConfigService implements Service container = registry.getService(KeycloakAdapterConfigService.SERVICE_NAME); - if (container != null) { - KeycloakAdapterConfigService service = (KeycloakAdapterConfigService)container.getValue(); - return service; - } - return null; - } - - public static KeycloakAdapterConfigService find(OperationContext context) { - return find(context.getServiceRegistry(true)); - } } diff --git a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakSubsystemAdd.java b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakSubsystemAdd.java index 0a490042be..386f8c57bc 100755 --- a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakSubsystemAdd.java +++ b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakSubsystemAdd.java @@ -82,18 +82,6 @@ class KeycloakSubsystemAdd extends AbstractBoottimeAddStepHandler { } } - @Override - protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model, ServiceVerificationHandler verificationHandler, List> newControllers) throws OperationFailedException { - super.performRuntime(context, operation, model, verificationHandler, newControllers); - - ServiceController controller = context.getServiceTarget() - .addService(KeycloakAdapterConfigService.SERVICE_NAME, KeycloakAdapterConfigService.INSTANCE) - .addListener(verificationHandler) - .setInitialMode(ServiceController.Mode.ACTIVE) - .install(); - newControllers.add(controller); - } - @Override protected boolean requiresRuntimeVerification() { return false; diff --git a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/RealmAddHandler.java b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/RealmAddHandler.java index 0d4a5d86d1..62c76e69b6 100755 --- a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/RealmAddHandler.java +++ b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/RealmAddHandler.java @@ -60,7 +60,7 @@ public final class RealmAddHandler extends AbstractAddStepHandler { @Override protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model, ServiceVerificationHandler verificationHandler, List> newControllers) throws OperationFailedException { - KeycloakAdapterConfigService ckService = KeycloakAdapterConfigService.find(context); + KeycloakAdapterConfigService ckService = KeycloakAdapterConfigService.getInstance(); ckService.addRealm(operation, context.resolveExpressions(model)); } } diff --git a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/RealmRemoveHandler.java b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/RealmRemoveHandler.java index a5c5441554..5cc319c0b2 100644 --- a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/RealmRemoveHandler.java +++ b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/RealmRemoveHandler.java @@ -35,7 +35,7 @@ public final class RealmRemoveHandler extends AbstractRemoveStepHandler { @Override protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model) throws OperationFailedException { - KeycloakAdapterConfigService ckService = KeycloakAdapterConfigService.find(context); + KeycloakAdapterConfigService ckService = KeycloakAdapterConfigService.getInstance(); ckService.removeRealm(operation); } } diff --git a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/RealmWriteAttributeHandler.java b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/RealmWriteAttributeHandler.java index 1902b076bc..13e91c5ce4 100755 --- a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/RealmWriteAttributeHandler.java +++ b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/RealmWriteAttributeHandler.java @@ -43,7 +43,7 @@ public class RealmWriteAttributeHandler extends AbstractWriteAttributeHandler hh) throws OperationFailedException { - KeycloakAdapterConfigService ckService = KeycloakAdapterConfigService.find(context); + KeycloakAdapterConfigService ckService = KeycloakAdapterConfigService.getInstance(); ckService.updateRealm(operation, attributeName, resolvedValue); hh.setHandback(ckService); diff --git a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/SecureDeploymentAddHandler.java b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/SecureDeploymentAddHandler.java index 99267dbe18..0c36146ec6 100755 --- a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/SecureDeploymentAddHandler.java +++ b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/SecureDeploymentAddHandler.java @@ -55,7 +55,7 @@ public final class SecureDeploymentAddHandler extends AbstractAddStepHandler { @Override protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model, ServiceVerificationHandler verificationHandler, List> newControllers) throws OperationFailedException { - KeycloakAdapterConfigService ckService = KeycloakAdapterConfigService.find(context); + KeycloakAdapterConfigService ckService = KeycloakAdapterConfigService.getInstance(); ckService.addSecureDeployment(operation, context.resolveExpressions(model)); } } diff --git a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/SecureDeploymentRemoveHandler.java b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/SecureDeploymentRemoveHandler.java index da0ca7e19d..23196a5fff 100644 --- a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/SecureDeploymentRemoveHandler.java +++ b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/SecureDeploymentRemoveHandler.java @@ -35,7 +35,7 @@ public final class SecureDeploymentRemoveHandler extends AbstractRemoveStepHandl @Override protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model) throws OperationFailedException { - KeycloakAdapterConfigService ckService = KeycloakAdapterConfigService.find(context); + KeycloakAdapterConfigService ckService = KeycloakAdapterConfigService.getInstance(); ckService.removeSecureDeployment(operation); } } diff --git a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/SecureDeploymentWriteAttributeHandler.java b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/SecureDeploymentWriteAttributeHandler.java index 2caca6ae64..6c87ac8601 100755 --- a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/SecureDeploymentWriteAttributeHandler.java +++ b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/SecureDeploymentWriteAttributeHandler.java @@ -44,7 +44,7 @@ public class SecureDeploymentWriteAttributeHandler extends AbstractWriteAttribut @Override protected boolean applyUpdateToRuntime(OperationContext context, ModelNode operation, String attributeName, ModelNode resolvedValue, ModelNode currentValue, HandbackHolder hh) throws OperationFailedException { - KeycloakAdapterConfigService ckService = KeycloakAdapterConfigService.find(context); + KeycloakAdapterConfigService ckService = KeycloakAdapterConfigService.getInstance(); hh.setHandback(ckService); ckService.updateSecureDeployment(operation, attributeName, resolvedValue); return false; diff --git a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerAddHandler.java b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerAddHandler.java index 591718e8b1..43d26ce969 100755 --- a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerAddHandler.java +++ b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerAddHandler.java @@ -69,7 +69,7 @@ public final class AuthServerAddHandler extends AbstractAddStepHandler { AuthServerUtil authServerUtil = new AuthServerUtil(operation); authServerUtil.addStepToUploadAuthServer(context, enabled); - KeycloakAdapterConfigService.INSTANCE.addServerDeployment(authServerUtil.getDeploymentName(), webContext); + KeycloakAdapterConfigService.getInstance().addServerDeployment(authServerUtil.getDeploymentName(), webContext); } @Override diff --git a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerDefinition.java b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerDefinition.java index 653d09ae3b..648e35d118 100755 --- a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerDefinition.java +++ b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerDefinition.java @@ -116,7 +116,7 @@ public class AuthServerDefinition extends SimpleResourceDefinition { @Override public void validateParameter(String paramName, ModelNode value) throws OperationFailedException { String strValue = value.asString(); - if (KeycloakAdapterConfigService.INSTANCE.isWebContextUsed(strValue)) { + if (KeycloakAdapterConfigService.getInstance().isWebContextUsed(strValue)) { throw new OperationFailedException("Can not set web-context to '" + strValue + "'. web-context must be unique among all deployments."); } } @@ -124,7 +124,7 @@ public class AuthServerDefinition extends SimpleResourceDefinition { @Override public void validateResolvedParameter(String paramName, ModelNode value) throws OperationFailedException { String strValue = value.asString(); - if (KeycloakAdapterConfigService.INSTANCE.isWebContextUsed(strValue)) { + if (KeycloakAdapterConfigService.getInstance().isWebContextUsed(strValue)) { throw new OperationFailedException("Can not set web-context to '" + strValue + "'. web-context must be unique among all deployments."); } } diff --git a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerRemoveHandler.java b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerRemoveHandler.java index f84e45ffe1..e80fbc6d75 100644 --- a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerRemoveHandler.java +++ b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerRemoveHandler.java @@ -45,7 +45,7 @@ public final class AuthServerRemoveHandler extends AbstractRemoveStepHandler { @Override protected void performRemove(OperationContext context, ModelNode operation, ModelNode model) throws OperationFailedException { String deploymentName = AuthServerUtil.getDeploymentName(operation); - KeycloakAdapterConfigService.INSTANCE.removeServerDeployment(deploymentName); + KeycloakAdapterConfigService.getInstance().removeServerDeployment(deploymentName); if (requiresRuntime(context)) { // don't do this on a domain controller addStepToRemoveAuthServer(context, deploymentName); diff --git a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerUtil.java b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerUtil.java index 9ccef2cd46..bf8074b4e5 100644 --- a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerUtil.java +++ b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerUtil.java @@ -46,6 +46,7 @@ import org.jboss.dmr.ModelNode; import org.jboss.modules.Module; import org.jboss.modules.ModuleIdentifier; import org.jboss.modules.ModuleLoadException; +import org.keycloak.subsystem.extension.KeycloakExtension; /** * Utility methods that help assemble and start an auth server. @@ -105,6 +106,9 @@ public class AuthServerUtil { op.get(ENABLED).set(isEnabled); op.get(PERSISTENT).set(false); // prevents writing this deployment out to standalone.xml + // Owner attribute is valid starting with WidlFly 9. Ignored in WildFly 8 + op.get("owner").set(new ModelNode().add("subsystem", KeycloakExtension.SUBSYSTEM_NAME)); + if (authServerUri == null) { throw new OperationFailedException("Keycloak Auth Server WAR not found in keycloak-subsystem module"); } diff --git a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerWriteAttributeHandler.java b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerWriteAttributeHandler.java index 48ffc320cf..6c5d6b3235 100755 --- a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerWriteAttributeHandler.java +++ b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerWriteAttributeHandler.java @@ -55,8 +55,8 @@ public class AuthServerWriteAttributeHandler extends ModelOnlyWriteAttributeHand if (attributeName.equals(AuthServerDefinition.WEB_CONTEXT.getName())) { - KeycloakAdapterConfigService.INSTANCE.removeServerDeployment(deploymentName); - KeycloakAdapterConfigService.INSTANCE.addServerDeployment(deploymentName, newValue.asString()); + KeycloakAdapterConfigService.getInstance().removeServerDeployment(deploymentName); + KeycloakAdapterConfigService.getInstance().addServerDeployment(deploymentName, newValue.asString()); if (isEnabled) { AuthServerUtil.addStepToRedeployAuthServer(context, deploymentName); } diff --git a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/KeycloakServerDeploymentProcessor.java b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/KeycloakServerDeploymentProcessor.java index dd66a01127..565310d8e2 100644 --- a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/KeycloakServerDeploymentProcessor.java +++ b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/KeycloakServerDeploymentProcessor.java @@ -34,7 +34,7 @@ public class KeycloakServerDeploymentProcessor implements DeploymentUnitProcesso public void deploy(DeploymentPhaseContext phaseContext) throws DeploymentUnitProcessingException { DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit(); String deploymentName = deploymentUnit.getName(); - KeycloakAdapterConfigService service = KeycloakAdapterConfigService.find(phaseContext.getServiceRegistry()); + KeycloakAdapterConfigService service = KeycloakAdapterConfigService.getInstance(); if (!service.isKeycloakServerDeployment(deploymentName)) { return; } diff --git a/model/api/src/main/java/org/keycloak/models/AdminRoles.java b/model/api/src/main/java/org/keycloak/models/AdminRoles.java index 8d465058eb..c067a1d842 100755 --- a/model/api/src/main/java/org/keycloak/models/AdminRoles.java +++ b/model/api/src/main/java/org/keycloak/models/AdminRoles.java @@ -9,25 +9,23 @@ public class AdminRoles { public static String ADMIN = "admin"; - // for admin application local to each realm + // for admin client local to each realm public static String REALM_ADMIN = "realm-admin"; public static String CREATE_REALM = "create-realm"; public static String VIEW_REALM = "view-realm"; public static String VIEW_USERS = "view-users"; - public static String VIEW_APPLICATIONS = "view-applications"; public static String VIEW_CLIENTS = "view-clients"; public static String VIEW_EVENTS = "view-events"; public static String VIEW_IDENTITY_PROVIDERS = "view-identity-providers"; public static String MANAGE_REALM = "manage-realm"; public static String MANAGE_USERS = "manage-users"; - public static String MANAGE_APPLICATIONS = "manage-applications"; public static String MANAGE_IDENTITY_PROVIDERS = "manage-identity-providers"; public static String MANAGE_CLIENTS = "manage-clients"; public static String MANAGE_EVENTS = "manage-events"; - public static String[] ALL_REALM_ROLES = {VIEW_REALM, VIEW_USERS, VIEW_APPLICATIONS, VIEW_CLIENTS, VIEW_EVENTS, VIEW_IDENTITY_PROVIDERS, MANAGE_REALM, MANAGE_USERS, MANAGE_APPLICATIONS, MANAGE_CLIENTS, MANAGE_EVENTS, MANAGE_IDENTITY_PROVIDERS}; + public static String[] ALL_REALM_ROLES = {VIEW_REALM, VIEW_USERS, VIEW_CLIENTS, VIEW_EVENTS, VIEW_IDENTITY_PROVIDERS, MANAGE_REALM, MANAGE_USERS, MANAGE_CLIENTS, MANAGE_EVENTS, MANAGE_IDENTITY_PROVIDERS}; } diff --git a/model/api/src/main/java/org/keycloak/models/ApplicationModel.java b/model/api/src/main/java/org/keycloak/models/ApplicationModel.java deleted file mode 100755 index 09f2a55e00..0000000000 --- a/model/api/src/main/java/org/keycloak/models/ApplicationModel.java +++ /dev/null @@ -1,56 +0,0 @@ -package org.keycloak.models; - -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * @author Bill Burke - * @version $Revision: 1 $ - */ -public interface ApplicationModel extends RoleContainerModel, ClientModel { - void updateApplication(); - - String getName(); - - void setName(String name); - - boolean isSurrogateAuthRequired(); - - void setSurrogateAuthRequired(boolean surrogateAuthRequired); - - String getManagementUrl(); - - void setManagementUrl(String url); - - String getBaseUrl(); - - void setBaseUrl(String url); - - List getDefaultRoles(); - - void addDefaultRole(String name); - - void updateDefaultRoles(String[] defaultRoles); - - Set getApplicationScopeMappings(ClientModel client); - - boolean isBearerOnly(); - void setBearerOnly(boolean only); - - int getNodeReRegistrationTimeout(); - - void setNodeReRegistrationTimeout(int timeout); - - Map getRegisteredNodes(); - - /** - * Register node or just update the 'lastReRegistration' time if this node is already registered - * - * @param nodeHost - * @param registrationTime - */ - void registerNode(String nodeHost, int registrationTime); - - void unregisterNode(String nodeHost); -} diff --git a/model/api/src/main/java/org/keycloak/models/ClientModel.java b/model/api/src/main/java/org/keycloak/models/ClientModel.java index e9de509700..026e35e242 100755 --- a/model/api/src/main/java/org/keycloak/models/ClientModel.java +++ b/model/api/src/main/java/org/keycloak/models/ClientModel.java @@ -8,7 +8,7 @@ import java.util.Set; * @author Bill Burke * @version $Revision: 1 $ */ -public interface ClientModel { +public interface ClientModel extends RoleContainerModel { // COMMON ATTRIBUTES @@ -16,20 +16,22 @@ public interface ClientModel { String PUBLIC_KEY = "publicKey"; String X509CERTIFICATE = "X509Certificate"; - /** - * Internal database key - * - * @return - */ + void updateClient(); + String getId(); - /** - * String exposed to outside world - * - * @return - */ String getClientId(); + void setClientId(String clientId); + + boolean isEnabled(); + + void setEnabled(boolean enabled); + + boolean isSurrogateAuthRequired(); + + void setSurrogateAuthRequired(boolean surrogateAuthRequired); + Set getWebOrigins(); void setWebOrigins(Set webOrigins); @@ -46,10 +48,28 @@ public interface ClientModel { void removeRedirectUri(String redirectUri); + String getManagementUrl(); - boolean isEnabled(); + void setManagementUrl(String url); - void setEnabled(boolean enabled); + String getBaseUrl(); + + void setBaseUrl(String url); + + List getDefaultRoles(); + + void addDefaultRole(String name); + + void updateDefaultRoles(String[] defaultRoles); + + Set getClientScopeMappings(ClientModel client); + + boolean isBearerOnly(); + void setBearerOnly(boolean only); + + int getNodeReRegistrationTimeout(); + + void setNodeReRegistrationTimeout(int timeout); boolean validateSecret(String secret); String getSecret(); @@ -76,13 +96,15 @@ public interface ClientModel { boolean isDirectGrantsOnly(); void setDirectGrantsOnly(boolean flag); + boolean isConsentRequired(); + void setConsentRequired(boolean consentRequired); + Set getScopeMappings(); void addScopeMapping(RoleModel role); void deleteScopeMapping(RoleModel role); Set getRealmScopeMappings(); boolean hasScope(RoleModel role); - RealmModel getRealm(); /** @@ -104,4 +126,16 @@ public interface ClientModel { void updateProtocolMapper(ProtocolMapperModel mapping); public ProtocolMapperModel getProtocolMapperById(String id); public ProtocolMapperModel getProtocolMapperByName(String protocol, String name); + + Map getRegisteredNodes(); + + /** + * Register node or just update the 'lastReRegistration' time if this node is already registered + * + * @param nodeHost + * @param registrationTime + */ + void registerNode(String nodeHost, int registrationTime); + + void unregisterNode(String nodeHost); } diff --git a/model/api/src/main/java/org/keycloak/models/Constants.java b/model/api/src/main/java/org/keycloak/models/Constants.java index 7374d7bc5b..edba3e3284 100755 --- a/model/api/src/main/java/org/keycloak/models/Constants.java +++ b/model/api/src/main/java/org/keycloak/models/Constants.java @@ -5,9 +5,9 @@ package org.keycloak.models; * @version $Revision: 1 $ */ public interface Constants { - String ADMIN_CONSOLE_APPLICATION = "security-admin-console"; + String ADMIN_CONSOLE_CLIENT_ID = "security-admin-console"; - String ACCOUNT_MANAGEMENT_APP = "account"; + String ACCOUNT_MANAGEMENT_CLIENT_ID = "account"; String INSTALLED_APP_URN = "urn:ietf:wg:oauth:2.0:oob"; String INSTALLED_APP_URL = "http://localhost"; diff --git a/model/api/src/main/java/org/keycloak/models/LDAPConstants.java b/model/api/src/main/java/org/keycloak/models/LDAPConstants.java index bf76be7be9..acab3e0d6e 100644 --- a/model/api/src/main/java/org/keycloak/models/LDAPConstants.java +++ b/model/api/src/main/java/org/keycloak/models/LDAPConstants.java @@ -29,5 +29,40 @@ public class LDAPConstants { public static final String BATCH_SIZE_FOR_SYNC = "batchSizeForSync"; public static final int DEFAULT_BATCH_SIZE_FOR_SYNC = 1000; + // Config option to specify if registrations will be synced or not + public static final String SYNC_REGISTRATIONS = "syncRegistrations"; + + // Applicable just for active directory public static final String USER_ACCOUNT_CONTROLS_AFTER_PASSWORD_UPDATE = "userAccountControlsAfterPasswordUpdate"; + + // Custom attributes on UserModel, which is mapped to LDAP + public static final String LDAP_ID = "LDAP_ID"; + public static final String LDAP_ENTRY_DN = "LDAP_ENTRY_DN"; + + + // Those are forked from Picketlink + public static final String GIVENNAME = "givenname"; + public static final String CN = "cn"; + public static final String SN = "sn"; + public static final String EMAIL = "mail"; + public static final String MEMBER = "member"; + public static final String MEMBER_OF = "memberOf"; + public static final String OBJECT_CLASS = "objectclass"; + public static final String UID = "uid"; + public static final String USER_PASSWORD_ATTRIBUTE = "userpassword"; + public static final String GROUP_OF_NAMES = "groupOfNames"; + public static final String GROUP_OF_ENTRIES = "groupOfEntries"; + public static final String GROUP_OF_UNIQUE_NAMES = "groupOfUniqueNames"; + + public static final String COMMA = ","; + public static final String EQUAL = "="; + public static final String SPACE_STRING = " "; + + public static final String CUSTOM_ATTRIBUTE_ENABLED = "enabled"; + public static final String CUSTOM_ATTRIBUTE_CREATE_DATE = "createDate"; + public static final String CUSTOM_ATTRIBUTE_EXPIRY_DATE = "expiryDate"; + public static final String ENTRY_UUID = "entryUUID"; + public static final String OBJECT_GUID = "objectGUID"; + public static final String CREATE_TIMESTAMP = "createTimeStamp"; + public static final String MODIFY_TIMESTAMP = "modifyTimeStamp"; } diff --git a/model/api/src/main/java/org/keycloak/models/OAuthClientModel.java b/model/api/src/main/java/org/keycloak/models/OAuthClientModel.java deleted file mode 100755 index 9f12728379..0000000000 --- a/model/api/src/main/java/org/keycloak/models/OAuthClientModel.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.keycloak.models; - -/** - * @author Bill Burke - * @version $Revision: 1 $ - */ -public interface OAuthClientModel extends ClientModel { - void setClientId(String id); - -} diff --git a/model/api/src/main/java/org/keycloak/models/RealmModel.java b/model/api/src/main/java/org/keycloak/models/RealmModel.java index 81d53a669e..17c88ea76e 100755 --- a/model/api/src/main/java/org/keycloak/models/RealmModel.java +++ b/model/api/src/main/java/org/keycloak/models/RealmModel.java @@ -19,15 +19,10 @@ public interface RealmModel extends RoleContainerModel { interface RealmCreationEvent extends ProviderEvent { RealmModel getCreatedRealm(); } + interface ClientCreationEvent extends ProviderEvent { ClientModel getCreatedClient(); } - interface ApplicationCreationEvent extends ClientCreationEvent { - ApplicationModel getCreatedApplication(); - } - interface OAuthClientCreationEvent extends ClientCreationEvent { - OAuthClientModel getCreatedOAuthClient(); - } String getId(); @@ -150,33 +145,21 @@ public interface RealmModel extends RoleContainerModel { void updateDefaultRoles(String[] defaultRoles); - ClientModel findClient(String clientId); + Map getClientNameMap(); - Map getApplicationNameMap(); + List getClients(); - List getApplications(); + ClientModel addClient(String name); - ApplicationModel addApplication(String name); + ClientModel addClient(String id, String clientId); - ApplicationModel addApplication(String id, String name); + boolean removeClient(String id); - boolean removeApplication(String id); - - ApplicationModel getApplicationById(String id); - ApplicationModel getApplicationByName(String name); + ClientModel getClientById(String id); + ClientModel getClientByClientId(String clientId); void updateRequiredCredentials(Set creds); - OAuthClientModel addOAuthClient(String name); - - OAuthClientModel addOAuthClient(String id, String name); - - OAuthClientModel getOAuthClient(String name); - OAuthClientModel getOAuthClientById(String id); - boolean removeOAuthClient(String id); - - List getOAuthClients(); - Map getBrowserSecurityHeaders(); void setBrowserSecurityHeaders(Map headers); @@ -249,11 +232,9 @@ public interface RealmModel extends RoleContainerModel { void setEnabledEventTypes(Set enabledEventTypes); - ApplicationModel getMasterAdminApp(); + ClientModel getMasterAdminClient(); - void setMasterAdminApp(ApplicationModel app); - - ClientModel findClientById(String id); + void setMasterAdminClient(ClientModel client); boolean isIdentityFederationEnabled(); diff --git a/model/api/src/main/java/org/keycloak/models/RealmProvider.java b/model/api/src/main/java/org/keycloak/models/RealmProvider.java index 58328b2cb5..17de99dd6a 100755 --- a/model/api/src/main/java/org/keycloak/models/RealmProvider.java +++ b/model/api/src/main/java/org/keycloak/models/RealmProvider.java @@ -1,7 +1,6 @@ package org.keycloak.models; import org.keycloak.provider.Provider; -import org.keycloak.provider.ProviderEvent; import java.util.List; @@ -19,8 +18,7 @@ public interface RealmProvider extends Provider { RealmModel getRealmByName(String name); RoleModel getRoleById(String id, RealmModel realm); - ApplicationModel getApplicationById(String id, RealmModel realm); - OAuthClientModel getOAuthClientById(String id, RealmModel realm); + ClientModel getClientById(String id, RealmModel realm); List getRealms(); boolean removeRealm(String id); diff --git a/model/api/src/main/java/org/keycloak/models/UserModel.java b/model/api/src/main/java/org/keycloak/models/UserModel.java index ee8ce80d0c..770cf03a8a 100755 --- a/model/api/src/main/java/org/keycloak/models/UserModel.java +++ b/model/api/src/main/java/org/keycloak/models/UserModel.java @@ -66,7 +66,7 @@ public interface UserModel { void updateCredentialDirectly(UserCredentialValueModel cred); Set getRealmRoleMappings(); - Set getApplicationRoleMappings(ApplicationModel app); + Set getClientRoleMappings(ClientModel app); boolean hasRole(RoleModel role); void grantRole(RoleModel role); Set getRoleMappings(); diff --git a/model/api/src/main/java/org/keycloak/models/UserSessionProvider.java b/model/api/src/main/java/org/keycloak/models/UserSessionProvider.java index b7421deb1f..3a642068cc 100755 --- a/model/api/src/main/java/org/keycloak/models/UserSessionProvider.java +++ b/model/api/src/main/java/org/keycloak/models/UserSessionProvider.java @@ -3,7 +3,6 @@ package org.keycloak.models; import org.keycloak.provider.Provider; import java.util.List; -import java.util.Map; /** * @author Bill Burke diff --git a/model/api/src/main/java/org/keycloak/models/entities/ApplicationEntity.java b/model/api/src/main/java/org/keycloak/models/entities/ApplicationEntity.java deleted file mode 100644 index c39ede4447..0000000000 --- a/model/api/src/main/java/org/keycloak/models/entities/ApplicationEntity.java +++ /dev/null @@ -1,79 +0,0 @@ -package org.keycloak.models.entities; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -/** - * @author Marek Posolda - */ -public class ApplicationEntity extends ClientEntity { - - private boolean surrogateAuthRequired; - private String managementUrl; - private String baseUrl; - private boolean bearerOnly; - private int nodeReRegistrationTimeout; - - // We are using names of defaultRoles (not ids) - private List defaultRoles = new ArrayList(); - - private Map registeredNodes; - - public boolean isSurrogateAuthRequired() { - return surrogateAuthRequired; - } - - public void setSurrogateAuthRequired(boolean surrogateAuthRequired) { - this.surrogateAuthRequired = surrogateAuthRequired; - } - - public String getManagementUrl() { - return managementUrl; - } - - public void setManagementUrl(String managementUrl) { - this.managementUrl = managementUrl; - } - - public String getBaseUrl() { - return baseUrl; - } - - public void setBaseUrl(String baseUrl) { - this.baseUrl = baseUrl; - } - - public boolean isBearerOnly() { - return bearerOnly; - } - - public void setBearerOnly(boolean bearerOnly) { - this.bearerOnly = bearerOnly; - } - - public List getDefaultRoles() { - return defaultRoles; - } - - public void setDefaultRoles(List defaultRoles) { - this.defaultRoles = defaultRoles; - } - - public int getNodeReRegistrationTimeout() { - return nodeReRegistrationTimeout; - } - - public void setNodeReRegistrationTimeout(int nodeReRegistrationTimeout) { - this.nodeReRegistrationTimeout = nodeReRegistrationTimeout; - } - - public Map getRegisteredNodes() { - return registeredNodes; - } - - public void setRegisteredNodes(Map registeredNodes) { - this.registeredNodes = registeredNodes; - } -} - diff --git a/model/api/src/main/java/org/keycloak/models/entities/ClientEntity.java b/model/api/src/main/java/org/keycloak/models/entities/ClientEntity.java old mode 100755 new mode 100644 index 9c24072d98..699c6d6244 --- a/model/api/src/main/java/org/keycloak/models/entities/ClientEntity.java +++ b/model/api/src/main/java/org/keycloak/models/entities/ClientEntity.java @@ -1,154 +1,236 @@ -package org.keycloak.models.entities; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * @author Marek Posolda - */ -public class ClientEntity extends AbstractIdentifiableEntity { - - private String name; - private boolean enabled; - private String secret; - private String protocol; - private long allowedClaimsMask; - private int notBefore; - private boolean publicClient; - private boolean fullScopeAllowed; - private boolean frontchannelLogout; - - private String realmId; - private Map attributes = new HashMap(); - - - private List webOrigins = new ArrayList(); - private List redirectUris = new ArrayList(); - private List scopeIds = new ArrayList(); - private List identityProviders = new ArrayList(); - private List protocolMappers = new ArrayList(); - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public boolean isEnabled() { - return enabled; - } - - public void setEnabled(boolean enabled) { - this.enabled = enabled; - } - - public String getSecret() { - return secret; - } - - public void setSecret(String secret) { - this.secret = secret; - } - - public int getNotBefore() { - return notBefore; - } - - public void setNotBefore(int notBefore) { - this.notBefore = notBefore; - } - - public boolean isPublicClient() { - return publicClient; - } - - public void setPublicClient(boolean publicClient) { - this.publicClient = publicClient; - } - - public String getRealmId() { - return realmId; - } - - public void setRealmId(String realmId) { - this.realmId = realmId; - } - - public List getWebOrigins() { - return webOrigins; - } - - public void setWebOrigins(List webOrigins) { - this.webOrigins = webOrigins; - } - - public List getRedirectUris() { - return redirectUris; - } - - public void setRedirectUris(List redirectUris) { - this.redirectUris = redirectUris; - } - - public List getScopeIds() { - return scopeIds; - } - - public void setScopeIds(List scopeIds) { - this.scopeIds = scopeIds; - } - - public boolean isFullScopeAllowed() { - return fullScopeAllowed; - } - - public void setFullScopeAllowed(boolean fullScopeAllowed) { - this.fullScopeAllowed = fullScopeAllowed; - } - - public String getProtocol() { - return protocol; - } - - public void setProtocol(String protocol) { - this.protocol = protocol; - } - - public Map getAttributes() { - return attributes; - } - - public void setAttributes(Map attributes) { - this.attributes = attributes; - } - - public boolean isFrontchannelLogout() { - return frontchannelLogout; - } - - public void setFrontchannelLogout(boolean frontchannelLogout) { - this.frontchannelLogout = frontchannelLogout; - } - - public List getIdentityProviders() { - return this.identityProviders; - } - - public void setIdentityProviders(List identityProviders) { - this.identityProviders = identityProviders; - } - - public List getProtocolMappers() { - return protocolMappers; - } - - public void setProtocolMappers(List protocolMappers) { - this.protocolMappers = protocolMappers; - } -} +package org.keycloak.models.entities; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author Marek Posolda + */ +public class ClientEntity extends AbstractIdentifiableEntity { + + private String clientId; + private String realmId; + private boolean enabled; + private String secret; + private String protocol; + private int notBefore; + private boolean publicClient; + private boolean fullScopeAllowed; + private boolean frontchannelLogout; + + private boolean surrogateAuthRequired; + private String managementUrl; + private String baseUrl; + private boolean bearerOnly; + private boolean consentRequired; + private boolean directGrantsOnly; + private int nodeReRegistrationTimeout; + + // We are using names of defaultRoles (not ids) + private List defaultRoles = new ArrayList(); + + private Map registeredNodes; + + private Map attributes = new HashMap(); + + private List webOrigins = new ArrayList(); + private List redirectUris = new ArrayList(); + private List scopeIds = new ArrayList(); + private List identityProviders = new ArrayList(); + private List protocolMappers = new ArrayList(); + + public String getClientId() { + return clientId; + } + + public void setClientId(String clientId) { + this.clientId = clientId; + } + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public String getSecret() { + return secret; + } + + public void setSecret(String secret) { + this.secret = secret; + } + + public int getNotBefore() { + return notBefore; + } + + public void setNotBefore(int notBefore) { + this.notBefore = notBefore; + } + + public boolean isPublicClient() { + return publicClient; + } + + public void setPublicClient(boolean publicClient) { + this.publicClient = publicClient; + } + + public String getRealmId() { + return realmId; + } + + public void setRealmId(String realmId) { + this.realmId = realmId; + } + + public List getWebOrigins() { + return webOrigins; + } + + public void setWebOrigins(List webOrigins) { + this.webOrigins = webOrigins; + } + + public List getRedirectUris() { + return redirectUris; + } + + public void setRedirectUris(List redirectUris) { + this.redirectUris = redirectUris; + } + + public List getScopeIds() { + return scopeIds; + } + + public void setScopeIds(List scopeIds) { + this.scopeIds = scopeIds; + } + + public boolean isFullScopeAllowed() { + return fullScopeAllowed; + } + + public void setFullScopeAllowed(boolean fullScopeAllowed) { + this.fullScopeAllowed = fullScopeAllowed; + } + + public String getProtocol() { + return protocol; + } + + public void setProtocol(String protocol) { + this.protocol = protocol; + } + + public Map getAttributes() { + return attributes; + } + + public void setAttributes(Map attributes) { + this.attributes = attributes; + } + + public boolean isFrontchannelLogout() { + return frontchannelLogout; + } + + public void setFrontchannelLogout(boolean frontchannelLogout) { + this.frontchannelLogout = frontchannelLogout; + } + + public List getIdentityProviders() { + return this.identityProviders; + } + + public void setIdentityProviders(List identityProviders) { + this.identityProviders = identityProviders; + } + + public List getProtocolMappers() { + return protocolMappers; + } + + public void setProtocolMappers(List protocolMappers) { + this.protocolMappers = protocolMappers; + } + + public boolean isSurrogateAuthRequired() { + return surrogateAuthRequired; + } + + public void setSurrogateAuthRequired(boolean surrogateAuthRequired) { + this.surrogateAuthRequired = surrogateAuthRequired; + } + + public String getManagementUrl() { + return managementUrl; + } + + public void setManagementUrl(String managementUrl) { + this.managementUrl = managementUrl; + } + + public String getBaseUrl() { + return baseUrl; + } + + public void setBaseUrl(String baseUrl) { + this.baseUrl = baseUrl; + } + + public boolean isBearerOnly() { + return bearerOnly; + } + + public void setBearerOnly(boolean bearerOnly) { + this.bearerOnly = bearerOnly; + } + + public boolean isConsentRequired() { + return consentRequired; + } + + public void setConsentRequired(boolean consentRequired) { + this.consentRequired = consentRequired; + } + + public boolean isDirectGrantsOnly() { + return directGrantsOnly; + } + + public void setDirectGrantsOnly(boolean directGrantsOnly) { + this.directGrantsOnly = directGrantsOnly; + } + + public List getDefaultRoles() { + return defaultRoles; + } + + public void setDefaultRoles(List defaultRoles) { + this.defaultRoles = defaultRoles; + } + + public int getNodeReRegistrationTimeout() { + return nodeReRegistrationTimeout; + } + + public void setNodeReRegistrationTimeout(int nodeReRegistrationTimeout) { + this.nodeReRegistrationTimeout = nodeReRegistrationTimeout; + } + + public Map getRegisteredNodes() { + return registeredNodes; + } + + public void setRegisteredNodes(Map registeredNodes) { + this.registeredNodes = registeredNodes; + } +} + diff --git a/model/api/src/main/java/org/keycloak/models/entities/OAuthClientEntity.java b/model/api/src/main/java/org/keycloak/models/entities/OAuthClientEntity.java deleted file mode 100755 index 79a00b4ad3..0000000000 --- a/model/api/src/main/java/org/keycloak/models/entities/OAuthClientEntity.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.keycloak.models.entities; - -/** - * @author Marek Posolda - */ -public class OAuthClientEntity extends ClientEntity { - protected boolean directGrantsOnly; - - public boolean isDirectGrantsOnly() { - return directGrantsOnly; - } - - public void setDirectGrantsOnly(boolean directGrantsOnly) { - this.directGrantsOnly = directGrantsOnly; - } -} diff --git a/model/api/src/main/java/org/keycloak/models/entities/RoleEntity.java b/model/api/src/main/java/org/keycloak/models/entities/RoleEntity.java index a961c70a78..a610d39d69 100644 --- a/model/api/src/main/java/org/keycloak/models/entities/RoleEntity.java +++ b/model/api/src/main/java/org/keycloak/models/entities/RoleEntity.java @@ -13,7 +13,7 @@ public class RoleEntity extends AbstractIdentifiableEntity { private List compositeRoleIds; private String realmId; - private String applicationId; + private String clientId; public String getName() { return name; @@ -47,11 +47,12 @@ public class RoleEntity extends AbstractIdentifiableEntity { this.realmId = realmId; } - public String getApplicationId() { - return applicationId; + public String getClientId() { + return clientId; } - public void setApplicationId(String applicationId) { - this.applicationId = applicationId; + public void setClientId(String clientId) { + this.clientId = clientId; } + } diff --git a/model/api/src/main/java/org/keycloak/models/utils/KeycloakModelUtils.java b/model/api/src/main/java/org/keycloak/models/utils/KeycloakModelUtils.java index af0b92d092..8ee918bd6f 100755 --- a/model/api/src/main/java/org/keycloak/models/utils/KeycloakModelUtils.java +++ b/model/api/src/main/java/org/keycloak/models/utils/KeycloakModelUtils.java @@ -1,8 +1,6 @@ package org.keycloak.models.utils; import org.bouncycastle.openssl.PEMWriter; -import org.keycloak.models.ApplicationModel; -import org.keycloak.models.ClaimMask; import org.keycloak.models.ClientModel; import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSessionFactory; @@ -174,8 +172,8 @@ public final class KeycloakModelUtils { return UUID.randomUUID().toString(); } - public static ApplicationModel createApplication(RealmModel realm, String name) { - ApplicationModel app = realm.addApplication(name); + public static ClientModel createClient(RealmModel realm, String name) { + ClientModel app = realm.addClient(name); generateSecret(app); app.setFullScopeAllowed(true); @@ -247,7 +245,7 @@ public final class KeycloakModelUtils { } } - public static String getMasterRealmAdminApplicationName(RealmModel realm) { + public static String getMasterRealmAdminApplicationClientId(RealmModel realm) { return realm.getName() + "-realm"; } } diff --git a/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java b/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java index 78a64ca99a..dc1124ae54 100755 --- a/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java +++ b/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java @@ -1,13 +1,10 @@ package org.keycloak.models.utils; -import org.keycloak.models.ApplicationModel; -import org.keycloak.models.ClaimMask; -import org.keycloak.models.ClientIdentityProviderMappingModel; import org.keycloak.models.ClientModel; +import org.keycloak.models.ClientIdentityProviderMappingModel; import org.keycloak.models.ClientSessionModel; import org.keycloak.models.FederatedIdentityModel; import org.keycloak.models.IdentityProviderModel; -import org.keycloak.models.OAuthClientModel; import org.keycloak.models.ProtocolMapperModel; import org.keycloak.models.RealmModel; import org.keycloak.models.RequiredCredentialModel; @@ -17,12 +14,11 @@ import org.keycloak.models.UserFederationProviderModel; import org.keycloak.models.UserModel; import org.keycloak.models.UserSessionModel; import org.keycloak.representations.idm.ApplicationRepresentation; -import org.keycloak.representations.idm.ClaimRepresentation; import org.keycloak.representations.idm.ClientIdentityProviderMappingRepresentation; +import org.keycloak.representations.idm.ClientRepresentation; import org.keycloak.representations.idm.CredentialRepresentation; import org.keycloak.representations.idm.FederatedIdentityRepresentation; import org.keycloak.representations.idm.IdentityProviderRepresentation; -import org.keycloak.representations.idm.OAuthClientRepresentation; import org.keycloak.representations.idm.ProtocolMapperRepresentation; import org.keycloak.representations.idm.RealmEventsConfigRepresentation; import org.keycloak.representations.idm.RealmRepresentation; @@ -30,6 +26,7 @@ import org.keycloak.representations.idm.RoleRepresentation; import org.keycloak.representations.idm.UserFederationProviderRepresentation; import org.keycloak.representations.idm.UserRepresentation; import org.keycloak.representations.idm.UserSessionRepresentation; +import org.keycloak.util.Time; import java.util.ArrayList; import java.util.HashMap; @@ -211,63 +208,60 @@ public class ModelToRepresentation { public static UserSessionRepresentation toRepresentation(UserSessionModel session) { UserSessionRepresentation rep = new UserSessionRepresentation(); rep.setId(session.getId()); - rep.setStart(((long)session.getStarted()) * 1000L); - rep.setLastAccess(((long)session.getLastSessionRefresh())* 1000L); + rep.setStart(Time.toMillis(session.getStarted())); + rep.setLastAccess(Time.toMillis(session.getLastSessionRefresh())); rep.setUser(session.getUser().getUsername()); rep.setIpAddress(session.getIpAddress()); for (ClientSessionModel clientSession : session.getClientSessions()) { ClientModel client = clientSession.getClient(); - if (client instanceof ApplicationModel) { - rep.getApplications().put(client.getId(), client.getClientId()); - } else if (client instanceof OAuthClientModel) { - rep.getClients().put(client.getId(), client.getClientId()); - } + rep.getClients().put(client.getId(), client.getClientId()); } return rep; } - public static ApplicationRepresentation toRepresentation(ApplicationModel applicationModel) { - ApplicationRepresentation rep = new ApplicationRepresentation(); - rep.setId(applicationModel.getId()); - rep.setName(applicationModel.getName()); - rep.setEnabled(applicationModel.isEnabled()); - rep.setAdminUrl(applicationModel.getManagementUrl()); - rep.setPublicClient(applicationModel.isPublicClient()); - rep.setFrontchannelLogout(applicationModel.isFrontchannelLogout()); - rep.setProtocol(applicationModel.getProtocol()); - rep.setAttributes(applicationModel.getAttributes()); - rep.setFullScopeAllowed(applicationModel.isFullScopeAllowed()); - rep.setBearerOnly(applicationModel.isBearerOnly()); - rep.setSurrogateAuthRequired(applicationModel.isSurrogateAuthRequired()); - rep.setBaseUrl(applicationModel.getBaseUrl()); - rep.setNotBefore(applicationModel.getNotBefore()); - rep.setNodeReRegistrationTimeout(applicationModel.getNodeReRegistrationTimeout()); + public static ClientRepresentation toRepresentation(ClientModel clientModel) { + ClientRepresentation rep = new ClientRepresentation(); + rep.setId(clientModel.getId()); + rep.setClientId(clientModel.getClientId()); + rep.setEnabled(clientModel.isEnabled()); + rep.setAdminUrl(clientModel.getManagementUrl()); + rep.setPublicClient(clientModel.isPublicClient()); + rep.setFrontchannelLogout(clientModel.isFrontchannelLogout()); + rep.setProtocol(clientModel.getProtocol()); + rep.setAttributes(clientModel.getAttributes()); + rep.setFullScopeAllowed(clientModel.isFullScopeAllowed()); + rep.setBearerOnly(clientModel.isBearerOnly()); + rep.setConsentRequired(clientModel.isConsentRequired()); + rep.setSurrogateAuthRequired(clientModel.isSurrogateAuthRequired()); + rep.setBaseUrl(clientModel.getBaseUrl()); + rep.setNotBefore(clientModel.getNotBefore()); + rep.setNodeReRegistrationTimeout(clientModel.getNodeReRegistrationTimeout()); - Set redirectUris = applicationModel.getRedirectUris(); + Set redirectUris = clientModel.getRedirectUris(); if (redirectUris != null) { - rep.setRedirectUris(new LinkedList(redirectUris)); + rep.setRedirectUris(new LinkedList<>(redirectUris)); } - Set webOrigins = applicationModel.getWebOrigins(); + Set webOrigins = clientModel.getWebOrigins(); if (webOrigins != null) { - rep.setWebOrigins(new LinkedList(webOrigins)); + rep.setWebOrigins(new LinkedList<>(webOrigins)); } - if (!applicationModel.getDefaultRoles().isEmpty()) { - rep.setDefaultRoles(applicationModel.getDefaultRoles().toArray(new String[0])); + if (!clientModel.getDefaultRoles().isEmpty()) { + rep.setDefaultRoles(clientModel.getDefaultRoles().toArray(new String[0])); } - if (!applicationModel.getRegisteredNodes().isEmpty()) { - rep.setRegisteredNodes(new HashMap(applicationModel.getRegisteredNodes())); + if (!clientModel.getRegisteredNodes().isEmpty()) { + rep.setRegisteredNodes(new HashMap<>(clientModel.getRegisteredNodes())); } - if (!applicationModel.getIdentityProviders().isEmpty()) { - rep.setIdentityProviders(toRepresentation(applicationModel.getIdentityProviders())); + if (!clientModel.getIdentityProviders().isEmpty()) { + rep.setIdentityProviders(toRepresentation(clientModel.getIdentityProviders())); } - if (!applicationModel.getProtocolMappers().isEmpty()) { - List mappings = new LinkedList(); - for (ProtocolMapperModel model : applicationModel.getProtocolMappers()) { + if (!clientModel.getProtocolMappers().isEmpty()) { + List mappings = new LinkedList<>(); + for (ProtocolMapperModel model : clientModel.getProtocolMappers()) { mappings.add(toRepresentation(model)); } rep.setProtocolMappers(mappings); @@ -291,43 +285,6 @@ public class ModelToRepresentation { return representations; } - public static OAuthClientRepresentation toRepresentation(OAuthClientModel model) { - OAuthClientRepresentation rep = new OAuthClientRepresentation(); - rep.setId(model.getId()); - rep.setName(model.getClientId()); - rep.setEnabled(model.isEnabled()); - rep.setPublicClient(model.isPublicClient()); - rep.setFrontchannelLogout(model.isFrontchannelLogout()); - rep.setProtocol(model.getProtocol()); - rep.setAttributes(model.getAttributes()); - rep.setFullScopeAllowed(model.isFullScopeAllowed()); - rep.setDirectGrantsOnly(model.isDirectGrantsOnly()); - Set redirectUris = model.getRedirectUris(); - if (redirectUris != null) { - rep.setRedirectUris(new LinkedList(redirectUris)); - } - - Set webOrigins = model.getWebOrigins(); - if (webOrigins != null) { - rep.setWebOrigins(new LinkedList(webOrigins)); - } - rep.setNotBefore(model.getNotBefore()); - - if (!model.getIdentityProviders().isEmpty()) { - rep.setIdentityProviders(toRepresentation(model.getIdentityProviders())); - } - - if (!model.getProtocolMappers().isEmpty()) { - List mappings = new LinkedList(); - for (ProtocolMapperModel mapper : model.getProtocolMappers()) { - mappings.add(toRepresentation(mapper)); - } - rep.setProtocolMappers(mappings); - } - - return rep; - } - public static UserFederationProviderRepresentation toRepresentation(UserFederationProviderModel model) { UserFederationProviderRepresentation rep = new UserFederationProviderRepresentation(); rep.setId(model.getId()); diff --git a/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java b/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java index 4ebc2d07cf..f830ac1f24 100755 --- a/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java +++ b/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java @@ -4,7 +4,6 @@ import net.iharder.Base64; import org.jboss.logging.Logger; import org.keycloak.enums.SslRequired; import org.keycloak.migration.MigrationProvider; -import org.keycloak.models.ApplicationModel; import org.keycloak.models.BrowserSecurityHeaders; import org.keycloak.models.ClaimMask; import org.keycloak.models.ClientIdentityProviderMappingModel; @@ -12,7 +11,6 @@ import org.keycloak.models.ClientModel; import org.keycloak.models.FederatedIdentityModel; import org.keycloak.models.IdentityProviderModel; import org.keycloak.models.KeycloakSession; -import org.keycloak.models.OAuthClientModel; import org.keycloak.models.PasswordPolicy; import org.keycloak.models.ProtocolMapperModel; import org.keycloak.models.RealmModel; @@ -24,6 +22,7 @@ import org.keycloak.models.UserModel; import org.keycloak.representations.idm.ApplicationRepresentation; import org.keycloak.representations.idm.ClaimRepresentation; import org.keycloak.representations.idm.ClientIdentityProviderMappingRepresentation; +import org.keycloak.representations.idm.ClientRepresentation; import org.keycloak.representations.idm.CredentialRepresentation; import org.keycloak.representations.idm.FederatedIdentityRepresentation; import org.keycloak.representations.idm.IdentityProviderRepresentation; @@ -52,6 +51,7 @@ public class RepresentationToModel { public static void importRealm(KeycloakSession session, RealmRepresentation rep, RealmModel newRealm) { convertDeprecatedSocialProviders(rep); + convertDeprecatedApplications(session, rep); newRealm.setName(rep.getRealm()); if (rep.isEnabled() != null) newRealm.setEnabled(rep.isEnabled()); @@ -129,8 +129,8 @@ public class RepresentationToModel { importIdentityProviders(rep, newRealm); - if (rep.getApplications() != null) { - Map appMap = createApplications(session, rep, newRealm); + if (rep.getClients() != null) { + createClients(session, rep, newRealm); } if (rep.getRoles() != null) { @@ -139,15 +139,15 @@ public class RepresentationToModel { createRole(newRealm, roleRep); } } - if (rep.getRoles().getApplication() != null) { - for (Map.Entry> entry : rep.getRoles().getApplication().entrySet()) { - ApplicationModel app = newRealm.getApplicationByName(entry.getKey()); - if (app == null) { + if (rep.getRoles().getClient() != null) { + for (Map.Entry> entry : rep.getRoles().getClient().entrySet()) { + ClientModel client = newRealm.getClientByClientId(entry.getKey()); + if (client == null) { throw new RuntimeException("App doesn't exist in role definitions: " + entry.getKey()); } for (RoleRepresentation roleRep : entry.getValue()) { // Application role may already exists (for example if it is defaultRole) - RoleModel role = roleRep.getId()!=null ? app.addRole(roleRep.getId(), roleRep.getName()) : app.addRole(roleRep.getName()); + RoleModel role = roleRep.getId()!=null ? client.addRole(roleRep.getId(), roleRep.getName()) : client.addRole(roleRep.getName()); role.setDescription(roleRep.getDescription()); } } @@ -159,14 +159,14 @@ public class RepresentationToModel { addComposites(role, roleRep, newRealm); } } - if (rep.getRoles().getApplication() != null) { - for (Map.Entry> entry : rep.getRoles().getApplication().entrySet()) { - ApplicationModel app = newRealm.getApplicationByName(entry.getKey()); - if (app == null) { + if (rep.getRoles().getClient() != null) { + for (Map.Entry> entry : rep.getRoles().getClient().entrySet()) { + ClientModel client = newRealm.getClientByClientId(entry.getKey()); + if (client == null) { throw new RuntimeException("App doesn't exist in role definitions: " + entry.getKey()); } for (RoleRepresentation roleRep : entry.getValue()) { - RoleModel role = app.getRole(roleRep.getName()); + RoleModel role = client.getRole(roleRep.getName()); addComposites(role, roleRep, newRealm); } } @@ -179,39 +179,34 @@ public class RepresentationToModel { newRealm.addDefaultRole(roleString.trim()); } } - // Setup application default roles - if (rep.getApplications() != null) { - for (ApplicationRepresentation resourceRep : rep.getApplications()) { + // Setup client default roles + if (rep.getClients() != null) { + for (ClientRepresentation resourceRep : rep.getClients()) { if (resourceRep.getDefaultRoles() != null) { - ApplicationModel appModel = newRealm.getApplicationByName(resourceRep.getName()); - appModel.updateDefaultRoles(resourceRep.getDefaultRoles()); + ClientModel clientModel = newRealm.getClientByClientId(resourceRep.getClientId()); + clientModel.updateDefaultRoles(resourceRep.getDefaultRoles()); } } } - if (rep.getOauthClients() != null) { - createOAuthClients(session, rep, newRealm); - } + // Now that all possible roles and clients are created, create scope mappings + Map appMap = newRealm.getClientNameMap(); - // Now that all possible roles and applications are created, create scope mappings + if (rep.getClientScopeMappings() != null) { - Map appMap = newRealm.getApplicationNameMap(); - - if (rep.getApplicationScopeMappings() != null) { - - for (Map.Entry> entry : rep.getApplicationScopeMappings().entrySet()) { - ApplicationModel app = appMap.get(entry.getKey()); + for (Map.Entry> entry : rep.getClientScopeMappings().entrySet()) { + ClientModel app = appMap.get(entry.getKey()); if (app == null) { - throw new RuntimeException("Unable to find application role mappings for app: " + entry.getKey()); + throw new RuntimeException("Unable to find client role mappings for client: " + entry.getKey()); } - createApplicationScopeMappings(newRealm, app, entry.getValue()); + createClientScopeMappings(newRealm, app, entry.getValue()); } } if (rep.getScopeMappings() != null) { for (ScopeMappingRepresentation scope : rep.getScopeMappings()) { - ClientModel client = newRealm.findClient(scope.getClient()); + ClientModel client = newRealm.getClientByClientId(scope.getClient()); if (client == null) { throw new RuntimeException("Unknown client specification in realm scope mappings"); } @@ -290,10 +285,6 @@ public class RepresentationToModel { rep.setIdentityProviders(identityProviders); } } - - rep.setSocial(null); - rep.setSocialProviders(null); - rep.setUpdateProfileOnInitialSocialLogin(false); } private static void convertDeprecatedSocialProviders(UserRepresentation user) { @@ -314,15 +305,73 @@ public class RepresentationToModel { user.setSocialLinks(null); } - private static List convertDeprecatedClaimsMask(KeycloakSession session, ClaimRepresentation claimRep) { - if (claimRep == null) { - return null; + private static void convertDeprecatedApplications(KeycloakSession session, RealmRepresentation realm) { + if (realm.getApplications() != null || realm.getOauthClients() != null) { + if (realm.getClients() == null) { + realm.setClients(new LinkedList()); + } + + List clients = new LinkedList<>(); + if (realm.getApplications() != null) { + clients.addAll(realm.getApplications()); + } + if (realm.getOauthClients() != null) { + clients.addAll(realm.getOauthClients()); + } + + for (ApplicationRepresentation app : clients) { + app.setClientId(app.getName()); + app.setName(null); + + if (app instanceof OAuthClientRepresentation) { + app.setConsentRequired(true); + app.setFullScopeAllowed(false); + } + + if (app.getProtocolMappers() == null && app.getClaims() != null) { + long mask = getClaimsMask(app.getClaims()); + List convertedProtocolMappers = session.getProvider(MigrationProvider.class).getMappersForClaimMask(mask); + app.setProtocolMappers(convertedProtocolMappers); + app.setClaims(null); + } + + realm.getClients().add(app); + } } - logger.warn("Using deprecated 'claims' configuration in JSON representation. It will be removed in future versions"); - long mask = getClaimsMask(claimRep); - MigrationProvider migrationProvider = session.getProvider(MigrationProvider.class); - return migrationProvider.getMappersForClaimMask(mask); + if (realm.getApplicationScopeMappings() != null && realm.getClientScopeMappings() == null) { + realm.setClientScopeMappings(realm.getApplicationScopeMappings()); + } + + if (realm.getRoles() != null && realm.getRoles().getApplication() != null && realm.getRoles().getClient() == null) { + realm.getRoles().setClient(realm.getRoles().getApplication()); + } + + if (realm.getUsers() != null) { + for (UserRepresentation user : realm.getUsers()) { + if (user.getApplicationRoles() != null && user.getClientRoles() == null) { + user.setClientRoles(user.getApplicationRoles()); + } + } + } + + if (realm.getRoles() != null && realm.getRoles().getRealm() != null) { + for (RoleRepresentation role : realm.getRoles().getRealm()) { + if (role.getComposites() != null && role.getComposites().getApplication() != null && role.getComposites().getClient() == null) { + role.getComposites().setClient(role.getComposites().getApplication()); + } + } + } + + if (realm.getRoles() != null && realm.getRoles().getClient() != null) { + for (Map.Entry> clientRoles : realm.getRoles().getClient().entrySet()) { + for (RoleRepresentation role : clientRoles.getValue()) { + if (role.getComposites() != null && role.getComposites().getApplication() != null && role.getComposites().getClient() == null) { + role.getComposites().setClient(role.getComposites().getApplication()); + } + } + } + } } public static void updateRealm(RealmRepresentation rep, RealmModel realm) { @@ -432,31 +481,30 @@ public class RepresentationToModel { role.addCompositeRole(realmRole); } } - if (roleRep.getComposites().getApplication() != null) { - for (Map.Entry> entry : roleRep.getComposites().getApplication().entrySet()) { - ApplicationModel app = realm.getApplicationByName(entry.getKey()); - if (app == null) { + if (roleRep.getComposites().getClient() != null) { + for (Map.Entry> entry : roleRep.getComposites().getClient().entrySet()) { + ClientModel client = realm.getClientByClientId(entry.getKey()); + if (client == null) { throw new RuntimeException("App doesn't exist in role definitions: " + roleRep.getName()); } for (String roleStr : entry.getValue()) { - RoleModel appRole = app.getRole(roleStr); - if (appRole == null) throw new RuntimeException("Unable to find composite app role: " + roleStr); - role.addCompositeRole(appRole); + RoleModel clientRole = client.getRole(roleStr); + if (clientRole == null) throw new RuntimeException("Unable to find composite client role: " + roleStr); + role.addCompositeRole(clientRole); } - } } } - // APPLICATIONS + // CLIENTS - private static Map createApplications(KeycloakSession session, RealmRepresentation rep, RealmModel realm) { - Map appMap = new HashMap(); - for (ApplicationRepresentation resourceRep : rep.getApplications()) { - ApplicationModel app = createApplication(session, realm, resourceRep, false); - appMap.put(app.getName(), app); + private static Map createClients(KeycloakSession session, RealmRepresentation rep, RealmModel realm) { + Map appMap = new HashMap(); + for (ClientRepresentation resourceRep : rep.getClients()) { + ClientModel app = createClient(session, realm, resourceRep, false); + appMap.put(app.getClientId(), app); } return appMap; } @@ -468,63 +516,57 @@ public class RepresentationToModel { * @param resourceRep * @return */ - public static ApplicationModel createApplication(KeycloakSession session, RealmModel realm, ApplicationRepresentation resourceRep, boolean addDefaultRoles) { - logger.debug("************ CREATE APPLICATION: {0}" + resourceRep.getName()); + public static ClientModel createClient(KeycloakSession session, RealmModel realm, ClientRepresentation resourceRep, boolean addDefaultRoles) { + logger.debug("Create client: {0}" + resourceRep.getClientId()); - if (resourceRep.getProtocolMappers() == null) { - List convertedProtocolMappers = convertDeprecatedClaimsMask(session, resourceRep.getClaims()); - if (convertedProtocolMappers != null) { - resourceRep.setProtocolMappers(convertedProtocolMappers); - } - } - - ApplicationModel applicationModel = resourceRep.getId()!=null ? realm.addApplication(resourceRep.getId(), resourceRep.getName()) : realm.addApplication(resourceRep.getName()); - if (resourceRep.isEnabled() != null) applicationModel.setEnabled(resourceRep.isEnabled()); - applicationModel.setManagementUrl(resourceRep.getAdminUrl()); + ClientModel client = resourceRep.getId()!=null ? realm.addClient(resourceRep.getId(), resourceRep.getClientId()) : realm.addClient(resourceRep.getClientId()); + if (resourceRep.isEnabled() != null) client.setEnabled(resourceRep.isEnabled()); + client.setManagementUrl(resourceRep.getAdminUrl()); if (resourceRep.isSurrogateAuthRequired() != null) - applicationModel.setSurrogateAuthRequired(resourceRep.isSurrogateAuthRequired()); - applicationModel.setBaseUrl(resourceRep.getBaseUrl()); - if (resourceRep.isBearerOnly() != null) applicationModel.setBearerOnly(resourceRep.isBearerOnly()); - if (resourceRep.isPublicClient() != null) applicationModel.setPublicClient(resourceRep.isPublicClient()); - if (resourceRep.isFrontchannelLogout() != null) applicationModel.setFrontchannelLogout(resourceRep.isFrontchannelLogout()); - if (resourceRep.getProtocol() != null) applicationModel.setProtocol(resourceRep.getProtocol()); + client.setSurrogateAuthRequired(resourceRep.isSurrogateAuthRequired()); + client.setBaseUrl(resourceRep.getBaseUrl()); + if (resourceRep.isBearerOnly() != null) client.setBearerOnly(resourceRep.isBearerOnly()); + if (resourceRep.isConsentRequired() != null) client.setConsentRequired(resourceRep.isConsentRequired()); + if (resourceRep.isPublicClient() != null) client.setPublicClient(resourceRep.isPublicClient()); + if (resourceRep.isFrontchannelLogout() != null) client.setFrontchannelLogout(resourceRep.isFrontchannelLogout()); + if (resourceRep.getProtocol() != null) client.setProtocol(resourceRep.getProtocol()); if (resourceRep.isFullScopeAllowed() != null) { - applicationModel.setFullScopeAllowed(resourceRep.isFullScopeAllowed()); + client.setFullScopeAllowed(resourceRep.isFullScopeAllowed()); } else { - applicationModel.setFullScopeAllowed(true); + client.setFullScopeAllowed(!client.isConsentRequired()); } if (resourceRep.getNodeReRegistrationTimeout() != null) { - applicationModel.setNodeReRegistrationTimeout(resourceRep.getNodeReRegistrationTimeout()); + client.setNodeReRegistrationTimeout(resourceRep.getNodeReRegistrationTimeout()); } else { - applicationModel.setNodeReRegistrationTimeout(-1); + client.setNodeReRegistrationTimeout(-1); } - applicationModel.updateApplication(); + client.updateClient(); if (resourceRep.getNotBefore() != null) { - applicationModel.setNotBefore(resourceRep.getNotBefore()); + client.setNotBefore(resourceRep.getNotBefore()); } - applicationModel.setSecret(resourceRep.getSecret()); - if (applicationModel.getSecret() == null) { - KeycloakModelUtils.generateSecret(applicationModel); + client.setSecret(resourceRep.getSecret()); + if (client.getSecret() == null) { + KeycloakModelUtils.generateSecret(client); } if (resourceRep.getAttributes() != null) { for (Map.Entry entry : resourceRep.getAttributes().entrySet()) { - applicationModel.setAttribute(entry.getKey(), entry.getValue()); + client.setAttribute(entry.getKey(), entry.getValue()); } } if (resourceRep.getRedirectUris() != null) { for (String redirectUri : resourceRep.getRedirectUris()) { - applicationModel.addRedirectUri(redirectUri); + client.addRedirectUri(redirectUri); } } if (resourceRep.getWebOrigins() != null) { for (String webOrigin : resourceRep.getWebOrigins()) { - logger.debugv("Application: {0} webOrigin: {1}", resourceRep.getName(), webOrigin); - applicationModel.addWebOrigin(webOrigin); + logger.debugv("Client: {0} webOrigin: {1}", resourceRep.getClientId(), webOrigin); + client.addWebOrigin(webOrigin); } } else { // add origins from redirect uris @@ -538,45 +580,46 @@ public class RepresentationToModel { if (uri.getPort() != -1) { origin += ":" + uri.getPort(); } - logger.debugv("adding default application origin: {0}" , origin); + logger.debugv("adding default client origin: {0}" , origin); origins.add(origin); } } if (origins.size() > 0) { - applicationModel.setWebOrigins(origins); + client.setWebOrigins(origins); } } } if (resourceRep.getRegisteredNodes() != null) { for (Map.Entry entry : resourceRep.getRegisteredNodes().entrySet()) { - applicationModel.registerNode(entry.getKey(), entry.getValue()); + client.registerNode(entry.getKey(), entry.getValue()); } } if (addDefaultRoles && resourceRep.getDefaultRoles() != null) { - applicationModel.updateDefaultRoles(resourceRep.getDefaultRoles()); + client.updateDefaultRoles(resourceRep.getDefaultRoles()); } if (resourceRep.getProtocolMappers() != null) { // first, remove all default/built in mappers - Set mappers = applicationModel.getProtocolMappers(); - for (ProtocolMapperModel mapper : mappers) applicationModel.removeProtocolMapper(mapper); + Set mappers = client.getProtocolMappers(); + for (ProtocolMapperModel mapper : mappers) client.removeProtocolMapper(mapper); for (ProtocolMapperRepresentation mapper : resourceRep.getProtocolMappers()) { - applicationModel.addProtocolMapper(toModel(mapper)); + client.addProtocolMapper(toModel(mapper)); } } - applicationModel.updateIdentityProviders(toModel(resourceRep.getIdentityProviders(), realm)); + client.updateIdentityProviders(toModel(resourceRep.getIdentityProviders(), realm)); - return applicationModel; + return client; } - public static void updateApplication(ApplicationRepresentation rep, ApplicationModel resource) { - if (rep.getName() != null) resource.setName(rep.getName()); + public static void updateClient(ClientRepresentation rep, ClientModel resource) { + if (rep.getClientId() != null) resource.setClientId(rep.getClientId()); if (rep.isEnabled() != null) resource.setEnabled(rep.isEnabled()); if (rep.isBearerOnly() != null) resource.setBearerOnly(rep.isBearerOnly()); + if (rep.isConsentRequired() != null) resource.setConsentRequired(rep.isConsentRequired()); if (rep.isPublicClient() != null) resource.setPublicClient(rep.isPublicClient()); if (rep.isFullScopeAllowed() != null) resource.setFullScopeAllowed(rep.isFullScopeAllowed()); if (rep.isFrontchannelLogout() != null) resource.setFrontchannelLogout(rep.isFrontchannelLogout()); @@ -584,7 +627,7 @@ public class RepresentationToModel { if (rep.getBaseUrl() != null) resource.setBaseUrl(rep.getBaseUrl()); if (rep.isSurrogateAuthRequired() != null) resource.setSurrogateAuthRequired(rep.isSurrogateAuthRequired()); if (rep.getNodeReRegistrationTimeout() != null) resource.setNodeReRegistrationTimeout(rep.getNodeReRegistrationTimeout()); - resource.updateApplication(); + resource.updateClient(); if (rep.getProtocol() != null) resource.setProtocol(rep.getProtocol()); if (rep.getAttributes() != null) { @@ -676,93 +719,18 @@ public class RepresentationToModel { return mask; } - // OAuth clients - - private static void createOAuthClients(KeycloakSession session, RealmRepresentation realmRep, RealmModel realm) { - for (OAuthClientRepresentation rep : realmRep.getOauthClients()) { - createOAuthClient(session, rep, realm); - } - } - - public static OAuthClientModel createOAuthClient(String id, String name, RealmModel realm) { - OAuthClientModel model = id!=null ? realm.addOAuthClient(id, name) : realm.addOAuthClient(name); - KeycloakModelUtils.generateSecret(model); - return model; - } - - public static OAuthClientModel createOAuthClient(KeycloakSession session, OAuthClientRepresentation rep, RealmModel realm) { - OAuthClientModel model = createOAuthClient(rep.getId(), rep.getName(), realm); - - model.updateIdentityProviders(toModel(rep.getIdentityProviders(), realm)); - - updateOAuthClient(session, rep, model); - return model; - } - - public static void updateOAuthClient(KeycloakSession session, OAuthClientRepresentation rep, OAuthClientModel model) { - if (rep.getProtocolMappers() == null) { - List convertedProtocolMappers = convertDeprecatedClaimsMask(session, rep.getClaims()); - if (convertedProtocolMappers != null) { - rep.setProtocolMappers(convertedProtocolMappers); - } - } - - if (rep.getName() != null) model.setClientId(rep.getName()); - if (rep.isEnabled() != null) model.setEnabled(rep.isEnabled()); - if (rep.isPublicClient() != null) model.setPublicClient(rep.isPublicClient()); - if (rep.isFrontchannelLogout() != null) model.setFrontchannelLogout(rep.isFrontchannelLogout()); - if (rep.isFullScopeAllowed() != null) model.setFullScopeAllowed(rep.isFullScopeAllowed()); - if (rep.isDirectGrantsOnly() != null) model.setDirectGrantsOnly(rep.isDirectGrantsOnly()); - if (rep.getNotBefore() != null) { - model.setNotBefore(rep.getNotBefore()); - } - if (rep.getSecret() != null) model.setSecret(rep.getSecret()); - List redirectUris = rep.getRedirectUris(); - if (redirectUris != null) { - model.setRedirectUris(new HashSet(redirectUris)); - } - - List webOrigins = rep.getWebOrigins(); - if (webOrigins != null) { - model.setWebOrigins(new HashSet(webOrigins)); - } - - if (rep.getNotBefore() != null) { - model.setNotBefore(rep.getNotBefore()); - } - if (rep.getProtocol() != null) model.setProtocol(rep.getProtocol()); - if (rep.getAttributes() != null) { - for (Map.Entry entry : rep.getAttributes().entrySet()) { - model.setAttribute(entry.getKey(), entry.getValue()); - } - } - - updateClientIdentityProviders(rep.getIdentityProviders(), model); - - if (rep.getProtocolMappers() != null) { - // first, remove all default/built in mappers - Set mappers = model.getProtocolMappers(); - for (ProtocolMapperModel mapper : mappers) model.removeProtocolMapper(mapper); - - for (ProtocolMapperRepresentation mapper : rep.getProtocolMappers()) { - model.addProtocolMapper(toModel(mapper)); - } - } - - } - // Scope mappings - public static void createApplicationScopeMappings(RealmModel realm, ApplicationModel applicationModel, List mappings) { + public static void createClientScopeMappings(RealmModel realm, ClientModel clientModel, List mappings) { for (ScopeMappingRepresentation mapping : mappings) { - ClientModel client = realm.findClient(mapping.getClient()); + ClientModel client = realm.getClientByClientId(mapping.getClient()); if (client == null) { - throw new RuntimeException("Unknown client specified in application scope mappings"); + throw new RuntimeException("Unknown client specified in client scope mappings"); } for (String roleString : mapping.getRoles()) { - RoleModel role = applicationModel.getRole(roleString.trim()); + RoleModel role = clientModel.getRole(roleString.trim()); if (role == null) { - role = applicationModel.addRole(roleString.trim()); + role = clientModel.addRole(roleString.trim()); } client.addScopeMapping(role); } @@ -771,7 +739,7 @@ public class RepresentationToModel { // Users - public static UserModel createUser(KeycloakSession session, RealmModel newRealm, UserRepresentation userRep, Map appMap) { + public static UserModel createUser(KeycloakSession session, RealmModel newRealm, UserRepresentation userRep, Map clientMap) { convertDeprecatedSocialProviders(userRep); // Import users just to user storage. Don't federate @@ -812,13 +780,13 @@ public class RepresentationToModel { user.grantRole(role); } } - if (userRep.getApplicationRoles() != null) { - for (Map.Entry> entry : userRep.getApplicationRoles().entrySet()) { - ApplicationModel app = appMap.get(entry.getKey()); - if (app == null) { - throw new RuntimeException("Unable to find application role mappings for app: " + entry.getKey()); + if (userRep.getClientRoles() != null) { + for (Map.Entry> entry : userRep.getClientRoles().entrySet()) { + ClientModel client = clientMap.get(entry.getKey()); + if (client == null) { + throw new RuntimeException("Unable to find client role mappings for client: " + entry.getKey()); } - createApplicationRoleMappings(app, user, entry.getValue()); + createClientRoleMappings(client, user, entry.getValue()); } } return user; @@ -853,15 +821,15 @@ public class RepresentationToModel { // Role mappings - public static void createApplicationRoleMappings(ApplicationModel applicationModel, UserModel user, List roleNames) { + public static void createClientRoleMappings(ClientModel clientModel, UserModel user, List roleNames) { if (user == null) { throw new RuntimeException("User not found"); } for (String roleName : roleNames) { - RoleModel role = applicationModel.getRole(roleName.trim()); + RoleModel role = clientModel.getRole(roleName.trim()); if (role == null) { - role = applicationModel.addRole(roleName.trim()); + role = clientModel.addRole(roleName.trim()); } user.grantRole(role); diff --git a/model/api/src/main/java/org/keycloak/models/utils/UserModelDelegate.java b/model/api/src/main/java/org/keycloak/models/utils/UserModelDelegate.java index 90f54bd2ff..0e84ca9ca4 100755 --- a/model/api/src/main/java/org/keycloak/models/utils/UserModelDelegate.java +++ b/model/api/src/main/java/org/keycloak/models/utils/UserModelDelegate.java @@ -1,6 +1,6 @@ package org.keycloak.models.utils; -import org.keycloak.models.ApplicationModel; +import org.keycloak.models.ClientModel; import org.keycloak.models.RoleModel; import org.keycloak.models.UserCredentialModel; import org.keycloak.models.UserCredentialValueModel; @@ -152,8 +152,8 @@ public class UserModelDelegate implements UserModel { } @Override - public Set getApplicationRoleMappings(ApplicationModel app) { - return delegate.getApplicationRoleMappings(app); + public Set getClientRoleMappings(ClientModel app) { + return delegate.getClientRoleMappings(app); } @Override diff --git a/model/api/src/main/java/org/keycloak/models/utils/reflection/NamedPropertyCriteria.java b/model/api/src/main/java/org/keycloak/models/utils/reflection/NamedPropertyCriteria.java new file mode 100644 index 0000000000..fc3b538d45 --- /dev/null +++ b/model/api/src/main/java/org/keycloak/models/utils/reflection/NamedPropertyCriteria.java @@ -0,0 +1,40 @@ +package org.keycloak.models.utils.reflection; + +import java.beans.Introspector; +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +/** + * A criteria that matches a property based on name + * + * @see PropertyCriteria + */ +public class NamedPropertyCriteria implements PropertyCriteria { + private final String[] propertyNames; + + public NamedPropertyCriteria(String... propertyNames) { + this.propertyNames = propertyNames; + } + + public boolean fieldMatches(Field f) { + for (String propertyName : propertyNames) { + if (propertyName.equals(f.getName())) { + return true; + } + } + return false; + } + + public boolean methodMatches(Method m) { + String[] validPrefix = {"get", "is"}; + for (String propertyName : propertyNames) { + for (String prefix : validPrefix) { + if (m.getName().startsWith(prefix) && + Introspector.decapitalize(m.getName().substring(prefix.length())).equals(propertyName)) { + return true; + } + } + } + return false; + } +} diff --git a/model/api/src/main/java/org/keycloak/models/utils/reflection/TypedPropertyCriteria.java b/model/api/src/main/java/org/keycloak/models/utils/reflection/TypedPropertyCriteria.java new file mode 100644 index 0000000000..93688a4102 --- /dev/null +++ b/model/api/src/main/java/org/keycloak/models/utils/reflection/TypedPropertyCriteria.java @@ -0,0 +1,71 @@ +package org.keycloak.models.utils.reflection; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +/** + * A criteria that matches a property based on its type + * + * @see PropertyCriteria + */ +public class TypedPropertyCriteria implements PropertyCriteria { + + /** + *

    Different options can be used to match a specific property based on its type. Regardless of the option + * chosen, if the property type equals the propertyClass it will be selected.

    • SUB_TYPE: + * Also consider properties where its type is a subtype of propertyClass. .
    • SUPER_TYPE: Also + * consider properties where its type is a superclass or superinterface of propertyClass. .
    + *

    + */ + public static enum MatchOption { + SUB_TYPE, SUPER_TYPE, ALL + } + + private final Class propertyClass; + private final MatchOption matchOption; + + public TypedPropertyCriteria(Class propertyClass) { + this(propertyClass, null); + } + + public TypedPropertyCriteria(Class propertyClass, MatchOption matchOption) { + if (propertyClass == null) { + throw new IllegalArgumentException("Property class can not be null."); + } + this.propertyClass = propertyClass; + this.matchOption = matchOption; + } + + public boolean fieldMatches(Field f) { + return match(f.getType()); + } + + public boolean methodMatches(Method m) { + return match(m.getReturnType()); + } + + private boolean match(Class type) { + if (propertyClass.equals(type)) { + return true; + } else { + boolean matchSubType = propertyClass.isAssignableFrom(type); + + if (MatchOption.SUB_TYPE == this.matchOption) { + return matchSubType; + } + + boolean matchSuperType = type.isAssignableFrom(propertyClass); + + if (MatchOption.SUPER_TYPE == this.matchOption) { + return matchSuperType; + } + + if (MatchOption.ALL == this.matchOption) { + return matchSubType || matchSuperType; + } + } + + return false; + } +} + diff --git a/model/file/src/main/java/org/keycloak/models/file/FileRealmProvider.java b/model/file/src/main/java/org/keycloak/models/file/FileRealmProvider.java index 52b3f39c95..3f23b5ca87 100644 --- a/model/file/src/main/java/org/keycloak/models/file/FileRealmProvider.java +++ b/model/file/src/main/java/org/keycloak/models/file/FileRealmProvider.java @@ -16,21 +16,20 @@ */ package org.keycloak.models.file; -import org.keycloak.models.file.adapter.RealmAdapter; -import java.util.ArrayList; -import org.keycloak.models.ApplicationModel; +import org.keycloak.connections.file.FileConnectionProvider; +import org.keycloak.connections.file.InMemoryModel; +import org.keycloak.models.ClientModel; import org.keycloak.models.KeycloakSession; -import org.keycloak.models.OAuthClientModel; +import org.keycloak.models.ModelDuplicateException; import org.keycloak.models.RealmModel; import org.keycloak.models.RealmProvider; import org.keycloak.models.RoleModel; +import org.keycloak.models.entities.RealmEntity; +import org.keycloak.models.file.adapter.RealmAdapter; import org.keycloak.models.utils.KeycloakModelUtils; +import java.util.ArrayList; import java.util.List; -import org.keycloak.connections.file.FileConnectionProvider; -import org.keycloak.connections.file.InMemoryModel; -import org.keycloak.models.ModelDuplicateException; -import org.keycloak.models.entities.RealmEntity; /** * Realm Provider for JSON persistence. @@ -100,13 +99,8 @@ public class FileRealmProvider implements RealmProvider { } @Override - public ApplicationModel getApplicationById(String id, RealmModel realm) { - return realm.getApplicationById(id); - } - - @Override - public OAuthClientModel getOAuthClientById(String id, RealmModel realm) { - return realm.getOAuthClientById(id); + public ClientModel getClientById(String id, RealmModel realm) { + return realm.getClientById(id); } } diff --git a/model/file/src/main/java/org/keycloak/models/file/FileUserProvider.java b/model/file/src/main/java/org/keycloak/models/file/FileUserProvider.java index 456831fc8b..850d1a7761 100644 --- a/model/file/src/main/java/org/keycloak/models/file/FileUserProvider.java +++ b/model/file/src/main/java/org/keycloak/models/file/FileUserProvider.java @@ -36,7 +36,7 @@ import java.util.Set; import java.util.regex.Pattern; import org.keycloak.connections.file.FileConnectionProvider; import org.keycloak.connections.file.InMemoryModel; -import org.keycloak.models.ApplicationModel; +import org.keycloak.models.ClientModel; import org.keycloak.models.CredentialValidationOutput; import org.keycloak.models.ModelDuplicateException; import org.keycloak.models.entities.FederatedIdentityEntity; @@ -276,7 +276,7 @@ public class FileUserProvider implements UserProvider { userModel.grantRole(realm.getRole(r)); } - for (ApplicationModel application : realm.getApplications()) { + for (ClientModel application : realm.getClients()) { for (String r : application.getDefaultRoles()) { userModel.grantRole(application.getRole(r)); } diff --git a/model/file/src/main/java/org/keycloak/models/file/adapter/ApplicationAdapter.java b/model/file/src/main/java/org/keycloak/models/file/adapter/ApplicationAdapter.java deleted file mode 100755 index 6edb24ad90..0000000000 --- a/model/file/src/main/java/org/keycloak/models/file/adapter/ApplicationAdapter.java +++ /dev/null @@ -1,322 +0,0 @@ -/* - * Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors - * as indicated by the @author tags. All rights reserved. - * - * 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.file.adapter; - -import org.keycloak.models.ApplicationModel; -import org.keycloak.models.ClientModel; -import org.keycloak.models.KeycloakSession; -import org.keycloak.models.RealmModel; -import org.keycloak.models.RoleModel; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import org.keycloak.connections.file.InMemoryModel; -import org.keycloak.models.ModelDuplicateException; -import org.keycloak.models.OAuthClientModel; -import org.keycloak.models.UserModel; -import org.keycloak.models.entities.ApplicationEntity; -import org.keycloak.models.entities.ClientEntity; -import org.keycloak.models.entities.RoleEntity; -import org.keycloak.models.utils.KeycloakModelUtils; - -/** - * ApplicationModel used for JSON persistence. - * - * @author Stan Silvert ssilvert@redhat.com (C) 2015 Red Hat Inc. - */ -public class ApplicationAdapter extends ClientAdapter implements ApplicationModel { - - private final ApplicationEntity applicationEntity; - private final InMemoryModel inMemoryModel; - - private final Map allRoles = new HashMap(); - - public ApplicationAdapter(KeycloakSession session, RealmModel realm, ApplicationEntity applicationEntity, ClientEntity clientEntity, InMemoryModel inMemoryModel) { - super(session, realm, clientEntity); - this.applicationEntity = applicationEntity; - this.inMemoryModel = inMemoryModel; - } - - public ApplicationEntity getApplicationEntity() { - return applicationEntity; - } - - @Override - public void updateApplication() { - } - - @Override - public String getName() { - return applicationEntity.getName(); - } - - @Override - public void setName(String name) { - if (appNameExists(name)) throw new ModelDuplicateException("Application named " + name + " already exists."); - applicationEntity.setName(name); - } - - private boolean appNameExists(String name) { - for (ApplicationModel app : realm.getApplications()) { - if (app == this) continue; - if (app.getName().equals(name)) return true; - } - - return false; - } - - @Override - public boolean isSurrogateAuthRequired() { - return applicationEntity.isSurrogateAuthRequired(); - } - - @Override - public void setSurrogateAuthRequired(boolean surrogateAuthRequired) { - applicationEntity.setSurrogateAuthRequired(surrogateAuthRequired); - } - - @Override - public String getManagementUrl() { - return applicationEntity.getManagementUrl(); - } - - @Override - public void setManagementUrl(String url) { - applicationEntity.setManagementUrl(url); - } - - @Override - public void setBaseUrl(String url) { - applicationEntity.setBaseUrl(url); - } - - @Override - public String getBaseUrl() { - return applicationEntity.getBaseUrl(); - } - - @Override - public boolean isBearerOnly() { - return applicationEntity.isBearerOnly(); - } - - @Override - public void setBearerOnly(boolean only) { - applicationEntity.setBearerOnly(only); - } - - @Override - public boolean isPublicClient() { - return applicationEntity.isPublicClient(); - } - - @Override - public void setPublicClient(boolean flag) { - applicationEntity.setPublicClient(flag); - } - - @Override - public boolean isDirectGrantsOnly() { - return false; // applications can't be grant only - } - - @Override - public void setDirectGrantsOnly(boolean flag) { - // applications can't be grant only - } - - - @Override - public RoleAdapter getRole(String name) { - for (RoleAdapter role : allRoles.values()) { - if (role.getName().equals(name)) return role; - } - return null; - } - - @Override - public RoleAdapter addRole(String name) { - return this.addRole(KeycloakModelUtils.generateId(), name); - } - - @Override - public RoleAdapter addRole(String id, String name) { - if (roleNameExists(name)) throw new ModelDuplicateException("Role named " + name + " already exists."); - RoleEntity roleEntity = new RoleEntity(); - roleEntity.setId(id); - roleEntity.setName(name); - roleEntity.setApplicationId(getId()); - - RoleAdapter role = new RoleAdapter(getRealm(), roleEntity, this); - allRoles.put(id, role); - - return role; - } - - private boolean roleNameExists(String name) { - for (RoleModel role : allRoles.values()) { - if (role.getName().equals(name)) return true; - } - - return false; - } - - @Override - public boolean removeRole(RoleModel role) { - boolean removed = (allRoles.remove(role.getId()) != null); - - // remove application roles from users - for (UserModel user : inMemoryModel.getUsers(realm.getId())) { - user.deleteRoleMapping(role); - } - - // delete scope mappings from applications - for (ApplicationModel app : realm.getApplications()) { - app.deleteScopeMapping(role); - } - - // delete scope mappings from oauth clients - for (OAuthClientModel oaClient : realm.getOAuthClients()) { - oaClient.deleteScopeMapping(role); - } - - // remove role from the realm - realm.removeRole(role); - - this.deleteScopeMapping(role); - - return removed; - } - - @Override - public Set getRoles() { - return new HashSet(allRoles.values()); - } - - @Override - public boolean hasScope(RoleModel role) { - if (super.hasScope(role)) { - return true; - } - Set roles = getRoles(); - if (roles.contains(role)) return true; - - for (RoleModel mapping : roles) { - if (mapping.hasRole(role)) return true; - } - return false; - } - - @Override - public Set getApplicationScopeMappings(ClientModel client) { - Set allScopes = client.getScopeMappings(); - - Set appRoles = new HashSet(); - for (RoleModel role : allScopes) { - RoleAdapter roleAdapter = (RoleAdapter)role; - if (getId().equals(roleAdapter.getRoleEntity().getApplicationId())) { - appRoles.add(role); - } - } - return appRoles; - } - - @Override - public List getDefaultRoles() { - return applicationEntity.getDefaultRoles(); - } - - @Override - public void addDefaultRole(String name) { - RoleModel role = getRole(name); - if (role == null) { - addRole(name); - } - - List defaultRoles = getDefaultRoles(); - if (defaultRoles.contains(name)) return; - - String[] defaultRoleNames = defaultRoles.toArray(new String[defaultRoles.size() + 1]); - defaultRoleNames[defaultRoleNames.length - 1] = name; - updateDefaultRoles(defaultRoleNames); - } - - @Override - public void updateDefaultRoles(String[] defaultRoles) { - List roleNames = new ArrayList(); - for (String roleName : defaultRoles) { - RoleModel role = getRole(roleName); - if (role == null) { - addRole(roleName); - } - - roleNames.add(roleName); - } - - applicationEntity.setDefaultRoles(roleNames); - } - - @Override - public int getNodeReRegistrationTimeout() { - return applicationEntity.getNodeReRegistrationTimeout(); - } - - @Override - public void setNodeReRegistrationTimeout(int timeout) { - applicationEntity.setNodeReRegistrationTimeout(timeout); - } - - @Override - public Map getRegisteredNodes() { - return applicationEntity.getRegisteredNodes() == null ? Collections.emptyMap() : Collections.unmodifiableMap(applicationEntity.getRegisteredNodes()); - } - - @Override - public void registerNode(String nodeHost, int registrationTime) { - if (applicationEntity.getRegisteredNodes() == null) { - applicationEntity.setRegisteredNodes(new HashMap()); - } - - applicationEntity.getRegisteredNodes().put(nodeHost, registrationTime); - } - - @Override - public void unregisterNode(String nodeHost) { - if (applicationEntity.getRegisteredNodes() == null) return; - - applicationEntity.getRegisteredNodes().remove(nodeHost); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || !(o instanceof ApplicationModel)) return false; - - ApplicationModel that = (ApplicationModel) o; - return that.getId().equals(getId()); - } - - @Override - public int hashCode() { - return getId().hashCode(); - } -} diff --git a/model/file/src/main/java/org/keycloak/models/file/adapter/ClientAdapter.java b/model/file/src/main/java/org/keycloak/models/file/adapter/ClientAdapter.java index 6c47bdf29e..18cc9c858b 100755 --- a/model/file/src/main/java/org/keycloak/models/file/adapter/ClientAdapter.java +++ b/model/file/src/main/java/org/keycloak/models/file/adapter/ClientAdapter.java @@ -1,420 +1,660 @@ -/* - * Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors - * as indicated by the @author tags. All rights reserved. - * - * 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.file.adapter; - -import org.keycloak.models.ClientModel; -import org.keycloak.models.KeycloakSession; -import org.keycloak.models.RealmModel; -import org.keycloak.models.RealmProvider; -import org.keycloak.models.RoleModel; -import org.keycloak.models.entities.ClientEntity; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; -import org.keycloak.models.ClientIdentityProviderMappingModel; -import org.keycloak.models.ProtocolMapperModel; -import org.keycloak.models.entities.ClientIdentityProviderMappingEntity; -import org.keycloak.models.entities.ProtocolMapperEntity; -import org.keycloak.models.utils.KeycloakModelUtils; - -/** - * ClientModel for JSON persistence. - * - * @author Stan Silvert ssilvert@redhat.com (C) 2015 Red Hat Inc. - */ -public abstract class ClientAdapter implements ClientModel { - - protected final ClientEntity clientEntity; - protected final RealmModel realm; - protected KeycloakSession session; - private final RealmProvider model; - - private final Map allScopeMappings = new HashMap(); - - public ClientAdapter(KeycloakSession session, RealmModel realm, ClientEntity clientEntity) { - this.clientEntity = clientEntity; - this.realm = realm; - this.session = session; - this.model = session.realms(); - } - - @Override - public String getId() { - return clientEntity.getId(); - } - - @Override - public String getClientId() { - return clientEntity.getName(); - } - - @Override - public Set getWebOrigins() { - Set result = new HashSet(); - if (clientEntity.getWebOrigins() != null) { - result.addAll(clientEntity.getWebOrigins()); - } - return result; - } - - @Override - public void setWebOrigins(Set webOrigins) { - List result = new ArrayList(); - result.addAll(webOrigins); - clientEntity.setWebOrigins(result); - } - - @Override - public void addWebOrigin(String webOrigin) { - Set webOrigins = getWebOrigins(); - webOrigins.add(webOrigin); - setWebOrigins(webOrigins); - } - - @Override - public void removeWebOrigin(String webOrigin) { - Set webOrigins = getWebOrigins(); - webOrigins.remove(webOrigin); - setWebOrigins(webOrigins); - } - - @Override - public Set getRedirectUris() { - Set result = new HashSet(); - if (clientEntity.getRedirectUris() != null) { - result.addAll(clientEntity.getRedirectUris()); - } - return result; - } - - @Override - public void setRedirectUris(Set redirectUris) { - List result = new ArrayList(); - result.addAll(redirectUris); - clientEntity.setRedirectUris(result); - } - - @Override - public void addRedirectUri(String redirectUri) { - if (clientEntity.getRedirectUris().contains(redirectUri)) return; - clientEntity.getRedirectUris().add(redirectUri); - } - - @Override - public void removeRedirectUri(String redirectUri) { - clientEntity.getRedirectUris().remove(redirectUri); - } - - @Override - public boolean isEnabled() { - return clientEntity.isEnabled(); - } - - @Override - public void setEnabled(boolean enabled) { - clientEntity.setEnabled(enabled); - } - - @Override - public boolean validateSecret(String secret) { - return secret.equals(clientEntity.getSecret()); - } - - @Override - public String getSecret() { - return clientEntity.getSecret(); - } - - @Override - public void setSecret(String secret) { - clientEntity.setSecret(secret); - } - - @Override - public boolean isPublicClient() { - return clientEntity.isPublicClient(); - } - - @Override - public void setPublicClient(boolean flag) { - clientEntity.setPublicClient(flag); - } - - - @Override - public boolean isFrontchannelLogout() { - return clientEntity.isFrontchannelLogout(); - } - - @Override - public void setFrontchannelLogout(boolean flag) { - clientEntity.setFrontchannelLogout(flag); - } - - @Override - public boolean isFullScopeAllowed() { - return clientEntity.isFullScopeAllowed(); - } - - @Override - public void setFullScopeAllowed(boolean value) { - clientEntity.setFullScopeAllowed(value); - - } - - @Override - public RealmModel getRealm() { - return realm; - } - - @Override - public int getNotBefore() { - return clientEntity.getNotBefore(); - } - - @Override - public void setNotBefore(int notBefore) { - clientEntity.setNotBefore(notBefore); - } - - @Override - public Set getScopeMappings() { - return new HashSet(allScopeMappings.values()); - } - - @Override - public Set getRealmScopeMappings() { - Set allScopes = getScopeMappings(); - - Set realmRoles = new HashSet(); - for (RoleModel role : allScopes) { - RoleAdapter roleAdapter = (RoleAdapter)role; - if (roleAdapter.isRealmRole()) { - realmRoles.add(role); - } - } - return realmRoles; - } - - @Override - public boolean hasScope(RoleModel role) { - if (isFullScopeAllowed()) return true; - Set roles = getScopeMappings(); - if (roles.contains(role)) return true; - - for (RoleModel mapping : roles) { - if (mapping.hasRole(role)) return true; - } - return false; - } - - - @Override - public void addScopeMapping(RoleModel role) { - allScopeMappings.put(role.getId(), role); - } - - @Override - public void deleteScopeMapping(RoleModel role) { - allScopeMappings.remove(role.getId()); - } - - @Override - public String getProtocol() { - return clientEntity.getProtocol(); - } - - @Override - public void setProtocol(String protocol) { - clientEntity.setProtocol(protocol); - - } - - @Override - public void setAttribute(String name, String value) { - clientEntity.getAttributes().put(name, value); - - } - - @Override - public void removeAttribute(String name) { - clientEntity.getAttributes().remove(name); - } - - @Override - public String getAttribute(String name) { - return clientEntity.getAttributes().get(name); - } - - @Override - public Map getAttributes() { - Map copy = new HashMap(); - copy.putAll(clientEntity.getAttributes()); - return copy; - } - - @Override - public Set getProtocolMappers() { - Set result = new HashSet(); - for (ProtocolMapperEntity entity : clientEntity.getProtocolMappers()) { - ProtocolMapperModel model = getProtocolMapperById(entity.getId()); - if (model != null) result.add(model); - } - return result; - } - - @Override - public ProtocolMapperModel addProtocolMapper(ProtocolMapperModel model) { - if (getProtocolMapperByName(model.getProtocol(), model.getName()) != null) { - throw new RuntimeException("protocol mapper name must be unique per protocol"); - } - ProtocolMapperEntity entity = new ProtocolMapperEntity(); - entity.setId(KeycloakModelUtils.generateId()); - entity.setProtocol(model.getProtocol()); - entity.setName(model.getName()); - entity.setProtocolMapper(model.getProtocolMapper()); - entity.setConfig(model.getConfig()); - entity.setConsentRequired(model.isConsentRequired()); - entity.setConsentText(model.getConsentText()); - clientEntity.getProtocolMappers().add(entity); - return entityToModel(entity); - } - - @Override - public void removeProtocolMapper(ProtocolMapperModel mapping) { - ProtocolMapperEntity toBeRemoved = null; - for (ProtocolMapperEntity entity : clientEntity.getProtocolMappers()) { - if (entity.getId().equals(mapping.getId())) { - toBeRemoved = entity; - break; - } - } - - clientEntity.getProtocolMappers().remove(toBeRemoved); - } - - @Override - public void updateProtocolMapper(ProtocolMapperModel mapping) { - ProtocolMapperEntity entity = getProtocolMapperEntityById(mapping.getId()); - entity.setProtocolMapper(mapping.getProtocolMapper()); - entity.setConsentRequired(mapping.isConsentRequired()); - entity.setConsentText(mapping.getConsentText()); - if (entity.getConfig() != null) { - entity.getConfig().clear(); - entity.getConfig().putAll(mapping.getConfig()); - } else { - entity.setConfig(mapping.getConfig()); - } - } - - protected ProtocolMapperEntity getProtocolMapperEntityById(String id) { - for (ProtocolMapperEntity entity : clientEntity.getProtocolMappers()) { - if (entity.getId().equals(id)) { - return entity; - } - } - return null; - } - - protected ProtocolMapperEntity getProtocolMapperEntityByName(String protocol, String name) { - for (ProtocolMapperEntity entity : clientEntity.getProtocolMappers()) { - if (entity.getProtocol().equals(protocol) && entity.getName().equals(name)) { - return entity; - } - } - return null; - - } - - @Override - public ProtocolMapperModel getProtocolMapperById(String id) { - ProtocolMapperEntity entity = getProtocolMapperEntityById(id); - if (entity == null) return null; - return entityToModel(entity); - } - - @Override - public ProtocolMapperModel getProtocolMapperByName(String protocol, String name) { - ProtocolMapperEntity entity = getProtocolMapperEntityByName(protocol, name); - if (entity == null) return null; - return entityToModel(entity); - } - - protected ProtocolMapperModel entityToModel(ProtocolMapperEntity entity) { - ProtocolMapperModel mapping = new ProtocolMapperModel(); - mapping.setId(entity.getId()); - mapping.setName(entity.getName()); - mapping.setProtocol(entity.getProtocol()); - mapping.setProtocolMapper(entity.getProtocolMapper()); - mapping.setConsentRequired(entity.isConsentRequired()); - mapping.setConsentText(entity.getConsentText()); - Map config = new HashMap(); - if (entity.getConfig() != null) config.putAll(entity.getConfig()); - mapping.setConfig(config); - return mapping; - } - - @Override - public void updateIdentityProviders(List identityProviders) { - List stored = new ArrayList(); - - for (ClientIdentityProviderMappingModel model : identityProviders) { - ClientIdentityProviderMappingEntity entity = new ClientIdentityProviderMappingEntity(); - - entity.setId(model.getIdentityProvider()); - entity.setRetrieveToken(model.isRetrieveToken()); - stored.add(entity); - } - - clientEntity.setIdentityProviders(stored); - } - - @Override - public List getIdentityProviders() { - List models = new ArrayList(); - - for (ClientIdentityProviderMappingEntity entity : clientEntity.getIdentityProviders()) { - ClientIdentityProviderMappingModel model = new ClientIdentityProviderMappingModel(); - - model.setIdentityProvider(entity.getId()); - model.setRetrieveToken(entity.isRetrieveToken()); - - models.add(model); - } - - return models; - } - - @Override - public boolean isAllowedRetrieveTokenFromIdentityProvider(String providerId) { - for (ClientIdentityProviderMappingEntity identityProviderMappingModel : clientEntity.getIdentityProviders()) { - if (identityProviderMappingModel.getId().equals(providerId)) { - return identityProviderMappingModel.isRetrieveToken(); - } - } - - return false; - } - -} +/* + * Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @author tags. All rights reserved. + * + * 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.file.adapter; + +import org.keycloak.models.ClientModel; +import org.keycloak.models.ClientIdentityProviderMappingModel; +import org.keycloak.models.KeycloakSession; +import org.keycloak.models.ProtocolMapperModel; +import org.keycloak.models.RealmModel; +import org.keycloak.models.RoleModel; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import org.keycloak.connections.file.InMemoryModel; +import org.keycloak.models.ModelDuplicateException; +import org.keycloak.models.UserModel; +import org.keycloak.models.entities.ClientEntity; +import org.keycloak.models.entities.ClientIdentityProviderMappingEntity; +import org.keycloak.models.entities.ProtocolMapperEntity; +import org.keycloak.models.entities.RoleEntity; +import org.keycloak.models.utils.KeycloakModelUtils; + +/** + * ApplicationModel used for JSON persistence. + * + * @author Stan Silvert ssilvert@redhat.com (C) 2015 Red Hat Inc. + */ +public class ClientAdapter implements ClientModel { + + private final RealmModel realm; + private KeycloakSession session; + private final ClientEntity entity; + private final InMemoryModel inMemoryModel; + + private final Map allRoles = new HashMap(); + private final Map allScopeMappings = new HashMap(); + + public ClientAdapter(KeycloakSession session, RealmModel realm, ClientEntity entity, InMemoryModel inMemoryModel) { + this.realm = realm; + this.session = session; + this.entity = entity; + this.inMemoryModel = inMemoryModel; + } + + @Override + public void updateClient() { + } + + @Override + public String getId() { + return entity.getId(); + } + + @Override + public Set getWebOrigins() { + Set result = new HashSet(); + if (entity.getWebOrigins() != null) { + result.addAll(entity.getWebOrigins()); + } + return result; + } + + @Override + public void setWebOrigins(Set webOrigins) { + List result = new ArrayList(); + result.addAll(webOrigins); + entity.setWebOrigins(result); + } + + @Override + public void addWebOrigin(String webOrigin) { + Set webOrigins = getWebOrigins(); + webOrigins.add(webOrigin); + setWebOrigins(webOrigins); + } + + @Override + public void removeWebOrigin(String webOrigin) { + Set webOrigins = getWebOrigins(); + webOrigins.remove(webOrigin); + setWebOrigins(webOrigins); + } + + @Override + public Set getRedirectUris() { + Set result = new HashSet(); + if (entity.getRedirectUris() != null) { + result.addAll(entity.getRedirectUris()); + } + return result; + } + + @Override + public void setRedirectUris(Set redirectUris) { + List result = new ArrayList(); + result.addAll(redirectUris); + entity.setRedirectUris(result); + } + + @Override + public void addRedirectUri(String redirectUri) { + if (entity.getRedirectUris().contains(redirectUri)) return; + entity.getRedirectUris().add(redirectUri); + } + + @Override + public void removeRedirectUri(String redirectUri) { + entity.getRedirectUris().remove(redirectUri); + } + + @Override + public boolean isEnabled() { + return entity.isEnabled(); + } + + @Override + public void setEnabled(boolean enabled) { + entity.setEnabled(enabled); + } + + @Override + public boolean validateSecret(String secret) { + return secret.equals(entity.getSecret()); + } + + @Override + public String getSecret() { + return entity.getSecret(); + } + + @Override + public void setSecret(String secret) { + entity.setSecret(secret); + } + + @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 boolean isFullScopeAllowed() { + return entity.isFullScopeAllowed(); + } + + @Override + public void setFullScopeAllowed(boolean value) { + entity.setFullScopeAllowed(value); + } + + @Override + public RealmModel getRealm() { + return realm; + } + + @Override + public int getNotBefore() { + return entity.getNotBefore(); + } + + @Override + public void setNotBefore(int notBefore) { + entity.setNotBefore(notBefore); + } + + @Override + public Set getScopeMappings() { + return new HashSet(allScopeMappings.values()); + } + + @Override + public Set getRealmScopeMappings() { + Set allScopes = getScopeMappings(); + + Set realmRoles = new HashSet(); + for (RoleModel role : allScopes) { + RoleAdapter roleAdapter = (RoleAdapter)role; + if (roleAdapter.isRealmRole()) { + realmRoles.add(role); + } + } + return realmRoles; + } + + @Override + public void addScopeMapping(RoleModel role) { + allScopeMappings.put(role.getId(), role); + } + + @Override + public void deleteScopeMapping(RoleModel role) { + allScopeMappings.remove(role.getId()); + } + + @Override + public String getProtocol() { + return entity.getProtocol(); + } + + @Override + public void setProtocol(String protocol) { + entity.setProtocol(protocol); + + } + + @Override + public void setAttribute(String name, String value) { + entity.getAttributes().put(name, value); + + } + + @Override + public void removeAttribute(String name) { + entity.getAttributes().remove(name); + } + + @Override + public String getAttribute(String name) { + return entity.getAttributes().get(name); + } + + @Override + public Map getAttributes() { + Map copy = new HashMap(); + copy.putAll(entity.getAttributes()); + return copy; + } + + @Override + public Set getProtocolMappers() { + Set result = new HashSet(); + for (ProtocolMapperEntity entity : this.entity.getProtocolMappers()) { + ProtocolMapperModel model = getProtocolMapperById(entity.getId()); + if (model != null) result.add(model); + } + return result; + } + + @Override + public ProtocolMapperModel addProtocolMapper(ProtocolMapperModel model) { + if (getProtocolMapperByName(model.getProtocol(), model.getName()) != null) { + throw new RuntimeException("protocol mapper name must be unique per protocol"); + } + ProtocolMapperEntity entity = new ProtocolMapperEntity(); + entity.setId(KeycloakModelUtils.generateId()); + entity.setProtocol(model.getProtocol()); + entity.setName(model.getName()); + entity.setProtocolMapper(model.getProtocolMapper()); + entity.setConfig(model.getConfig()); + entity.setConsentRequired(model.isConsentRequired()); + entity.setConsentText(model.getConsentText()); + this.entity.getProtocolMappers().add(entity); + return entityToModel(entity); + } + + @Override + public void removeProtocolMapper(ProtocolMapperModel mapping) { + ProtocolMapperEntity toBeRemoved = null; + for (ProtocolMapperEntity e : entity.getProtocolMappers()) { + if (e.getId().equals(mapping.getId())) { + toBeRemoved = e; + break; + } + } + + entity.getProtocolMappers().remove(toBeRemoved); + } + + @Override + public void updateProtocolMapper(ProtocolMapperModel mapping) { + ProtocolMapperEntity entity = getProtocolMapperEntityById(mapping.getId()); + entity.setProtocolMapper(mapping.getProtocolMapper()); + entity.setConsentRequired(mapping.isConsentRequired()); + entity.setConsentText(mapping.getConsentText()); + if (entity.getConfig() != null) { + entity.getConfig().clear(); + entity.getConfig().putAll(mapping.getConfig()); + } else { + entity.setConfig(mapping.getConfig()); + } + } + + protected ProtocolMapperEntity getProtocolMapperEntityById(String id) { + for (ProtocolMapperEntity e : entity.getProtocolMappers()) { + if (e.getId().equals(id)) { + return e; + } + } + return null; + } + + protected ProtocolMapperEntity getProtocolMapperEntityByName(String protocol, String name) { + for (ProtocolMapperEntity e : entity.getProtocolMappers()) { + if (e.getProtocol().equals(protocol) && e.getName().equals(name)) { + return e; + } + } + return null; + + } + + @Override + public ProtocolMapperModel getProtocolMapperById(String id) { + ProtocolMapperEntity entity = getProtocolMapperEntityById(id); + if (entity == null) return null; + return entityToModel(entity); + } + + @Override + public ProtocolMapperModel getProtocolMapperByName(String protocol, String name) { + ProtocolMapperEntity entity = getProtocolMapperEntityByName(protocol, name); + if (entity == null) return null; + return entityToModel(entity); + } + + protected ProtocolMapperModel entityToModel(ProtocolMapperEntity entity) { + ProtocolMapperModel mapping = new ProtocolMapperModel(); + mapping.setId(entity.getId()); + mapping.setName(entity.getName()); + mapping.setProtocol(entity.getProtocol()); + mapping.setProtocolMapper(entity.getProtocolMapper()); + mapping.setConsentRequired(entity.isConsentRequired()); + mapping.setConsentText(entity.getConsentText()); + Map config = new HashMap(); + if (entity.getConfig() != null) config.putAll(entity.getConfig()); + mapping.setConfig(config); + return mapping; + } + + @Override + public void updateIdentityProviders(List identityProviders) { + List stored = new ArrayList(); + + for (ClientIdentityProviderMappingModel model : identityProviders) { + ClientIdentityProviderMappingEntity entity = new ClientIdentityProviderMappingEntity(); + + entity.setId(model.getIdentityProvider()); + entity.setRetrieveToken(model.isRetrieveToken()); + stored.add(entity); + } + + entity.setIdentityProviders(stored); + } + + @Override + public List getIdentityProviders() { + List models = new ArrayList<>(); + + for (ClientIdentityProviderMappingEntity e : entity.getIdentityProviders()) { + ClientIdentityProviderMappingModel model = new ClientIdentityProviderMappingModel(); + + model.setIdentityProvider(e.getId()); + model.setRetrieveToken(e.isRetrieveToken()); + + models.add(model); + } + + return models; + } + + @Override + public boolean isAllowedRetrieveTokenFromIdentityProvider(String providerId) { + for (ClientIdentityProviderMappingEntity identityProviderMappingModel : entity.getIdentityProviders()) { + if (identityProviderMappingModel.getId().equals(providerId)) { + return identityProviderMappingModel.isRetrieveToken(); + } + } + + return false; + } + + @Override + public String getClientId() { + return entity.getClientId(); + } + + @Override + public void setClientId(String clientId) { + if (appNameExists(clientId)) throw new ModelDuplicateException("Application named " + clientId + " already exists."); + entity.setClientId(clientId); + } + + private boolean appNameExists(String name) { + for (ClientModel app : realm.getClients()) { + if (app == this) continue; + if (app.getClientId().equals(name)) return true; + } + + return false; + } + + @Override + public boolean isSurrogateAuthRequired() { + return entity.isSurrogateAuthRequired(); + } + + @Override + public void setSurrogateAuthRequired(boolean surrogateAuthRequired) { + entity.setSurrogateAuthRequired(surrogateAuthRequired); + } + + @Override + public String getManagementUrl() { + return entity.getManagementUrl(); + } + + @Override + public void setManagementUrl(String url) { + entity.setManagementUrl(url); + } + + @Override + public void setBaseUrl(String url) { + entity.setBaseUrl(url); + } + + @Override + public String getBaseUrl() { + return entity.getBaseUrl(); + } + + @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 isDirectGrantsOnly() { + return entity.isDirectGrantsOnly(); + } + + @Override + public void setDirectGrantsOnly(boolean flag) { + entity.setDirectGrantsOnly(flag); + } + + @Override + public RoleAdapter getRole(String name) { + for (RoleAdapter role : allRoles.values()) { + if (role.getName().equals(name)) return role; + } + return null; + } + + @Override + public RoleAdapter addRole(String name) { + return this.addRole(KeycloakModelUtils.generateId(), name); + } + + @Override + public RoleAdapter addRole(String id, String name) { + if (roleNameExists(name)) throw new ModelDuplicateException("Role named " + name + " already exists."); + RoleEntity roleEntity = new RoleEntity(); + roleEntity.setId(id); + roleEntity.setName(name); + roleEntity.setClientId(getId()); + + RoleAdapter role = new RoleAdapter(getRealm(), roleEntity, this); + allRoles.put(id, role); + + return role; + } + + private boolean roleNameExists(String name) { + for (RoleModel role : allRoles.values()) { + if (role.getName().equals(name)) return true; + } + + return false; + } + + @Override + public boolean removeRole(RoleModel role) { + boolean removed = (allRoles.remove(role.getId()) != null); + + // remove application roles from users + for (UserModel user : inMemoryModel.getUsers(realm.getId())) { + user.deleteRoleMapping(role); + } + + // delete scope mappings from applications + for (ClientModel app : realm.getClients()) { + app.deleteScopeMapping(role); + } + + // remove role from the realm + realm.removeRole(role); + + this.deleteScopeMapping(role); + + return removed; + } + + @Override + public Set getRoles() { + return new HashSet(allRoles.values()); + } + + @Override + public boolean hasScope(RoleModel role) { + if (isFullScopeAllowed()) return true; + Set roles = getScopeMappings(); + if (roles.contains(role)) return true; + + for (RoleModel mapping : roles) { + if (mapping.hasRole(role)) return true; + } + roles = getRoles(); + if (roles.contains(role)) return true; + + for (RoleModel mapping : roles) { + if (mapping.hasRole(role)) return true; + } + return false; + } + + @Override + public Set getClientScopeMappings(ClientModel client) { + Set allScopes = client.getScopeMappings(); + + Set appRoles = new HashSet(); + for (RoleModel role : allScopes) { + RoleAdapter roleAdapter = (RoleAdapter)role; + if (getId().equals(roleAdapter.getRoleEntity().getClientId())) { + appRoles.add(role); + } + } + return appRoles; + } + + @Override + public List getDefaultRoles() { + return entity.getDefaultRoles(); + } + + @Override + public void addDefaultRole(String name) { + RoleModel role = getRole(name); + if (role == null) { + addRole(name); + } + + List defaultRoles = getDefaultRoles(); + if (defaultRoles.contains(name)) return; + + String[] defaultRoleNames = defaultRoles.toArray(new String[defaultRoles.size() + 1]); + defaultRoleNames[defaultRoleNames.length - 1] = name; + updateDefaultRoles(defaultRoleNames); + } + + @Override + public void updateDefaultRoles(String[] defaultRoles) { + List roleNames = new ArrayList(); + for (String roleName : defaultRoles) { + RoleModel role = getRole(roleName); + if (role == null) { + addRole(roleName); + } + + roleNames.add(roleName); + } + + entity.setDefaultRoles(roleNames); + } + + @Override + public int getNodeReRegistrationTimeout() { + return entity.getNodeReRegistrationTimeout(); + } + + @Override + public void setNodeReRegistrationTimeout(int timeout) { + entity.setNodeReRegistrationTimeout(timeout); + } + + @Override + public Map getRegisteredNodes() { + return entity.getRegisteredNodes() == null ? Collections.emptyMap() : Collections.unmodifiableMap(entity.getRegisteredNodes()); + } + + @Override + public void registerNode(String nodeHost, int registrationTime) { + if (entity.getRegisteredNodes() == null) { + entity.setRegisteredNodes(new HashMap()); + } + + entity.getRegisteredNodes().put(nodeHost, registrationTime); + } + + @Override + public void unregisterNode(String nodeHost) { + if (entity.getRegisteredNodes() == null) return; + + entity.getRegisteredNodes().remove(nodeHost); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || !(o instanceof ClientModel)) return false; + + ClientModel that = (ClientModel) o; + return that.getId().equals(getId()); + } + + @Override + public int hashCode() { + return getId().hashCode(); + } +} diff --git a/model/file/src/main/java/org/keycloak/models/file/adapter/OAuthClientAdapter.java b/model/file/src/main/java/org/keycloak/models/file/adapter/OAuthClientAdapter.java deleted file mode 100755 index 0069df801a..0000000000 --- a/model/file/src/main/java/org/keycloak/models/file/adapter/OAuthClientAdapter.java +++ /dev/null @@ -1,45 +0,0 @@ -package org.keycloak.models.file.adapter; - -import org.keycloak.models.KeycloakSession; -import org.keycloak.models.ModelDuplicateException; -import org.keycloak.models.OAuthClientModel; -import org.keycloak.models.RealmModel; -import org.keycloak.models.entities.OAuthClientEntity; - -/** - * OAuthClientModel for JSON persistence. - * - * @author Marek Posolda - */ -public class OAuthClientAdapter extends ClientAdapter implements OAuthClientModel { - - private final OAuthClientEntity oauthClientEntity; - - public OAuthClientAdapter(KeycloakSession session, RealmModel realm, OAuthClientEntity oauthClientEntity) { - super(session, realm, oauthClientEntity); - this.oauthClientEntity = oauthClientEntity; - } - - public String getName() { - return oauthClientEntity.getName(); - } - - @Override - public void setClientId(String id) { - if (id == null) throw new NullPointerException("id == null"); - if (oauthClientEntity.getName().equals(id)) return; // allow setting name to same name - RealmAdapter realmAdapter = (RealmAdapter)realm; - if (realmAdapter.hasOAuthClientWithClientId(id)) throw new ModelDuplicateException("Realm already has OAuthClient with client id " + id); - oauthClientEntity.setName(id); - } - - @Override - public boolean isDirectGrantsOnly() { - return oauthClientEntity.isDirectGrantsOnly(); - } - - @Override - public void setDirectGrantsOnly(boolean flag) { - oauthClientEntity.setDirectGrantsOnly(flag); - } -} diff --git a/model/file/src/main/java/org/keycloak/models/file/adapter/RealmAdapter.java b/model/file/src/main/java/org/keycloak/models/file/adapter/RealmAdapter.java index a1490ed9e6..31b4bfc869 100755 --- a/model/file/src/main/java/org/keycloak/models/file/adapter/RealmAdapter.java +++ b/model/file/src/main/java/org/keycloak/models/file/adapter/RealmAdapter.java @@ -1,1264 +1,1167 @@ -/* - * Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors - * as indicated by the @author tags. All rights reserved. - * - * 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.file.adapter; - -import org.keycloak.enums.SslRequired; -import org.keycloak.models.ApplicationModel; -import org.keycloak.models.ClientModel; -import org.keycloak.models.IdentityProviderMapperModel; -import org.keycloak.models.IdentityProviderModel; -import org.keycloak.models.KeycloakSession; -import org.keycloak.models.OAuthClientModel; -import org.keycloak.models.PasswordPolicy; -import org.keycloak.models.RealmModel; -import org.keycloak.models.RequiredCredentialModel; -import org.keycloak.models.RoleModel; -import org.keycloak.models.UserFederationProviderModel; -import org.keycloak.models.entities.IdentityProviderMapperEntity; -import org.keycloak.models.entities.RequiredCredentialEntity; -import org.keycloak.models.entities.UserFederationProviderEntity; -import org.keycloak.models.utils.KeycloakModelUtils; - -import java.security.Key; -import java.security.PrivateKey; -import java.security.PublicKey; -import java.security.cert.X509Certificate; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; -import org.keycloak.connections.file.InMemoryModel; -import org.keycloak.models.ModelDuplicateException; -import org.keycloak.models.UserModel; -import org.keycloak.models.entities.ApplicationEntity; -import org.keycloak.models.entities.ClientEntity; -import org.keycloak.models.entities.OAuthClientEntity; -import org.keycloak.models.entities.RealmEntity; -import org.keycloak.models.entities.RoleEntity; - -/** - * RealmModel for JSON persistence. - * - * @author Stan Silvert ssilvert@redhat.com (C) 2015 Red Hat Inc. - */ -public class RealmAdapter implements RealmModel { - - private final InMemoryModel inMemoryModel; - private final RealmEntity realm; - - protected volatile transient PublicKey publicKey; - protected volatile transient PrivateKey privateKey; - protected volatile transient X509Certificate certificate; - protected volatile transient Key codeSecretKey; - - private volatile transient PasswordPolicy passwordPolicy; - private volatile transient KeycloakSession session; - - private final Map allApps = new HashMap(); - private ApplicationModel masterAdminApp = null; - private final Map allRoles = new HashMap(); - private final Map allOAuthClients = new HashMap(); - private final Map allIdProviders = new HashMap(); - - public RealmAdapter(KeycloakSession session, RealmEntity realm, InMemoryModel inMemoryModel) { - this.session = session; - this.realm = realm; - this.inMemoryModel = inMemoryModel; - } - - public RealmEntity getRealmEnity() { - return realm; - } - - @Override - public String getId() { - return realm.getId(); - } - - @Override - public String getName() { - return realm.getName(); - } - - @Override - public void setName(String name) { - if (getName() == null) { - realm.setName(name); - return; - } - - if (getName().equals(name)) return; // allow setting name to same value - - if (inMemoryModel.getRealmByName(name) != null) throw new ModelDuplicateException("Realm " + name + " already exists."); - realm.setName(name); - } - - @Override - public boolean isEnabled() { - return realm.isEnabled(); - } - - @Override - public void setEnabled(boolean enabled) { - realm.setEnabled(enabled); - } - - @Override - public SslRequired getSslRequired() { - return SslRequired.valueOf(realm.getSslRequired()); - } - - @Override - public void setSslRequired(SslRequired sslRequired) { - realm.setSslRequired(sslRequired.name()); - } - - @Override - public boolean isPasswordCredentialGrantAllowed() { - return realm.isPasswordCredentialGrantAllowed(); - } - - @Override - public void setPasswordCredentialGrantAllowed(boolean passwordCredentialGrantAllowed) { - realm.setPasswordCredentialGrantAllowed(passwordCredentialGrantAllowed); - } - - @Override - public boolean isRegistrationAllowed() { - return realm.isRegistrationAllowed(); - } - - @Override - public void setRegistrationAllowed(boolean registrationAllowed) { - realm.setRegistrationAllowed(registrationAllowed); - } - - @Override - public boolean isRegistrationEmailAsUsername() { - return realm.isRegistrationEmailAsUsername(); - } - - @Override - public void setRegistrationEmailAsUsername(boolean registrationEmailAsUsername) { - realm.setRegistrationEmailAsUsername(registrationEmailAsUsername); - } - - @Override - public boolean isRememberMe() { - return realm.isRememberMe(); - } - - @Override - public void setRememberMe(boolean rememberMe) { - realm.setRememberMe(rememberMe); - } - - @Override - public boolean isBruteForceProtected() { - return realm.isBruteForceProtected(); - } - - @Override - public void setBruteForceProtected(boolean value) { - realm.setBruteForceProtected(value); - } - - @Override - public int getMaxFailureWaitSeconds() { - return realm.getMaxFailureWaitSeconds(); - } - - @Override - public void setMaxFailureWaitSeconds(int val) { - realm.setMaxFailureWaitSeconds(val); - } - - @Override - public int getWaitIncrementSeconds() { - return realm.getWaitIncrementSeconds(); - } - - @Override - public void setWaitIncrementSeconds(int val) { - realm.setWaitIncrementSeconds(val); - } - - @Override - public long getQuickLoginCheckMilliSeconds() { - return realm.getQuickLoginCheckMilliSeconds(); - } - - @Override - public void setQuickLoginCheckMilliSeconds(long val) { - realm.setQuickLoginCheckMilliSeconds(val); - } - - @Override - public int getMinimumQuickLoginWaitSeconds() { - return realm.getMinimumQuickLoginWaitSeconds(); - } - - @Override - public void setMinimumQuickLoginWaitSeconds(int val) { - realm.setMinimumQuickLoginWaitSeconds(val); - } - - - @Override - public int getMaxDeltaTimeSeconds() { - return realm.getMaxDeltaTimeSeconds(); - } - - @Override - public void setMaxDeltaTimeSeconds(int val) { - realm.setMaxDeltaTimeSeconds(val); - } - - @Override - public int getFailureFactor() { - return realm.getFailureFactor(); - } - - @Override - public void setFailureFactor(int failureFactor) { - realm.setFailureFactor(failureFactor); - } - - - @Override - public boolean isVerifyEmail() { - return realm.isVerifyEmail(); - } - - @Override - public void setVerifyEmail(boolean verifyEmail) { - realm.setVerifyEmail(verifyEmail); - } - - @Override - public boolean isResetPasswordAllowed() { - return realm.isResetPasswordAllowed(); - } - - @Override - public void setResetPasswordAllowed(boolean resetPassword) { - realm.setResetPasswordAllowed(resetPassword); - } - - @Override - public PasswordPolicy getPasswordPolicy() { - if (passwordPolicy == null) { - passwordPolicy = new PasswordPolicy(realm.getPasswordPolicy()); - } - return passwordPolicy; - } - - @Override - public void setPasswordPolicy(PasswordPolicy policy) { - this.passwordPolicy = policy; - realm.setPasswordPolicy(policy.toString()); - } - - @Override - public int getNotBefore() { - return realm.getNotBefore(); - } - - @Override - public void setNotBefore(int notBefore) { - realm.setNotBefore(notBefore); - } - - - @Override - public int getSsoSessionIdleTimeout() { - return realm.getSsoSessionIdleTimeout(); - } - - @Override - public void setSsoSessionIdleTimeout(int seconds) { - realm.setSsoSessionIdleTimeout(seconds); - } - - @Override - public int getSsoSessionMaxLifespan() { - return realm.getSsoSessionMaxLifespan(); - } - - @Override - public void setSsoSessionMaxLifespan(int seconds) { - realm.setSsoSessionMaxLifespan(seconds); - } - - @Override - public int getAccessTokenLifespan() { - return realm.getAccessTokenLifespan(); - } - - @Override - public void setAccessTokenLifespan(int tokenLifespan) { - realm.setAccessTokenLifespan(tokenLifespan); - } - - @Override - public int getAccessCodeLifespan() { - return realm.getAccessCodeLifespan(); - } - - @Override - public void setAccessCodeLifespan(int accessCodeLifespan) { - realm.setAccessCodeLifespan(accessCodeLifespan); - } - - @Override - public int getAccessCodeLifespanUserAction() { - return realm.getAccessCodeLifespanUserAction(); - } - - @Override - public void setAccessCodeLifespanUserAction(int accessCodeLifespanUserAction) { - realm.setAccessCodeLifespanUserAction(accessCodeLifespanUserAction); - } - - @Override - public String getPublicKeyPem() { - return realm.getPublicKeyPem(); - } - - @Override - public void setPublicKeyPem(String publicKeyPem) { - realm.setPublicKeyPem(publicKeyPem); - this.publicKey = null; - } - - @Override - public X509Certificate getCertificate() { - if (certificate != null) return certificate; - certificate = KeycloakModelUtils.getCertificate(getCertificatePem()); - return certificate; - } - - @Override - public void setCertificate(X509Certificate certificate) { - this.certificate = certificate; - String certificatePem = KeycloakModelUtils.getPemFromCertificate(certificate); - setCertificatePem(certificatePem); - } - - @Override - public String getCertificatePem() { - return realm.getCertificatePem(); - } - - @Override - public void setCertificatePem(String certificate) { - realm.setCertificatePem(certificate); - - } - - - @Override - public String getPrivateKeyPem() { - return realm.getPrivateKeyPem(); - } - - @Override - public void setPrivateKeyPem(String privateKeyPem) { - realm.setPrivateKeyPem(privateKeyPem); - this.privateKey = null; - } - - @Override - public PublicKey getPublicKey() { - if (publicKey != null) return publicKey; - publicKey = KeycloakModelUtils.getPublicKey(getPublicKeyPem()); - return publicKey; - } - - @Override - public void setPublicKey(PublicKey publicKey) { - this.publicKey = publicKey; - String publicKeyPem = KeycloakModelUtils.getPemFromKey(publicKey); - setPublicKeyPem(publicKeyPem); - } - - @Override - public PrivateKey getPrivateKey() { - if (privateKey != null) return privateKey; - privateKey = KeycloakModelUtils.getPrivateKey(getPrivateKeyPem()); - return privateKey; - } - - @Override - public void setPrivateKey(PrivateKey privateKey) { - this.privateKey = privateKey; - String privateKeyPem = KeycloakModelUtils.getPemFromKey(privateKey); - setPrivateKeyPem(privateKeyPem); - } - - @Override - public String getCodeSecret() { - return realm.getCodeSecret(); - } - - @Override - public Key getCodeSecretKey() { - if (codeSecretKey == null) { - codeSecretKey = KeycloakModelUtils.getSecretKey(getCodeSecret()); - } - return codeSecretKey; - } - - @Override - public void setCodeSecret(String codeSecret) { - realm.setCodeSecret(codeSecret); - } - - @Override - public String getLoginTheme() { - return realm.getLoginTheme(); - } - - @Override - public void setLoginTheme(String name) { - realm.setLoginTheme(name); - } - - @Override - public String getAccountTheme() { - return realm.getAccountTheme(); - } - - @Override - public void setAccountTheme(String name) { - realm.setAccountTheme(name); - } - - @Override - public String getAdminTheme() { - return realm.getAdminTheme(); - } - - @Override - public void setAdminTheme(String name) { - realm.setAdminTheme(name); - } - - @Override - public String getEmailTheme() { - return realm.getEmailTheme(); - } - - @Override - public void setEmailTheme(String name) { - realm.setEmailTheme(name); - } - - @Override - public RoleAdapter getRole(String name) { - for (RoleAdapter role : allRoles.values()) { - if (role.getName().equals(name)) return role; - } - return null; - } - - @Override - public RoleModel addRole(String name) { - return this.addRole(KeycloakModelUtils.generateId(), name); - } - - @Override - public RoleModel addRole(String id, String name) { - if (id == null) throw new NullPointerException("id == null"); - if (name == null) throw new NullPointerException("name == null"); - if (hasRoleWithName(name)) throw new ModelDuplicateException("Realm already contains role with name " + name + "."); - - RoleEntity roleEntity = new RoleEntity(); - roleEntity.setId(id); - roleEntity.setName(name); - roleEntity.setRealmId(getId()); - - RoleAdapter roleModel = new RoleAdapter(this, roleEntity, this); - allRoles.put(id, roleModel); - return roleModel; - } - - @Override - public boolean removeRole(RoleModel role) { - return removeRoleById(role.getId()); - } - - @Override - public boolean removeRoleById(String id) { - if (id == null) throw new NullPointerException("id == null"); - - // try realm roles first - if (allRoles.remove(id) != null) return true; - - for (ApplicationModel app : getApplications()) { - for (RoleModel appRole : app.getRoles()) { - if (id.equals(appRole.getId())) { - app.removeRole(appRole); - return true; - } - } - } - - return false; - } - - @Override - public Set getRoles() { - return new HashSet(allRoles.values()); - } - - @Override - public RoleModel getRoleById(String id) { - RoleModel found = allRoles.get(id); - if (found != null) return found; - - for (ApplicationModel app : getApplications()) { - for (RoleModel appRole : app.getRoles()) { - if (appRole.getId().equals(id)) return appRole; - } - } - - return null; - } - - @Override - public List getDefaultRoles() { - return realm.getDefaultRoles(); - } - - @Override - public void addDefaultRole(String name) { - RoleModel role = getRole(name); - if (role == null) { - addRole(name); - } - - List roleNames = getDefaultRoles(); - if (roleNames.contains(name)) throw new IllegalArgumentException("Realm " + realm.getName() + " already contains default role named " + name); - - roleNames.add(name); - realm.setDefaultRoles(roleNames); - } - - boolean hasRoleWithName(String name) { - for (RoleModel role : allRoles.values()) { - if (role.getName().equals(name)) return true; - } - - return false; - } - - @Override - public void updateDefaultRoles(String[] defaultRoles) { - List roleNames = new ArrayList(); - for (String roleName : defaultRoles) { - RoleModel role = getRole(roleName); - if (role == null) { - addRole(roleName); - } - - roleNames.add(roleName); - } - - realm.setDefaultRoles(roleNames); - } - - @Override - public ClientModel findClient(String clientId) { - ClientModel model = getApplicationByName(clientId); - if (model != null) return model; - return getOAuthClient(clientId); - } - - @Override - public ClientModel findClientById(String id) { - ClientModel clientModel = getApplicationById(id); - if (clientModel != null) return clientModel; - return getOAuthClientById(id); - } - - - - @Override - public ApplicationModel getApplicationById(String id) { - return allApps.get(id); - } - - @Override - public ApplicationModel getApplicationByName(String name) { - for (ApplicationModel app : getApplications()) { - if (app.getName().equals(name)) return app; - } - - return null; - } - - @Override - public Map getApplicationNameMap() { - Map resourceMap = new HashMap(); - for (ApplicationModel resource : getApplications()) { - resourceMap.put(resource.getName(), resource); - } - return resourceMap; - } - - @Override - public List getApplications() { - return new ArrayList(allApps.values()); - } - - @Override - public ApplicationModel addApplication(String name) { - return this.addApplication(KeycloakModelUtils.generateId(), name); - } - - @Override - public ApplicationModel addApplication(String id, String name) { - if (name == null) throw new NullPointerException("name == null"); - if (id == null) throw new NullPointerException("id == null"); - - if (getApplicationNameMap().containsKey(name)) { - throw new ModelDuplicateException("Application named '" + name + "' already exists."); - } - - ApplicationEntity appEntity = new ApplicationEntity(); - appEntity.setId(id); - appEntity.setName(name); - appEntity.setRealmId(getId()); - appEntity.setEnabled(true); - - ClientEntity clientEntity = new ClientEntity(); - clientEntity.setId(id); - clientEntity.setName(name); - clientEntity.setRealmId(getId()); - clientEntity.setEnabled(true); - - final ApplicationModel app = new ApplicationAdapter(session, this, appEntity, clientEntity, inMemoryModel); - session.getKeycloakSessionFactory().publish(new ApplicationCreationEvent() { - @Override - public ApplicationModel getCreatedApplication() { - return app; - } - - @Override - public ClientModel getCreatedClient() { - return app; - } - }); - - allApps.put(id, app); - - return app; - } - - @Override - public boolean removeApplication(String id) { - ApplicationModel appToBeRemoved = this.getApplicationById(id); - if (appToBeRemoved == null) return false; - - // remove any composite role assignments for this app - for (RoleModel role : this.getRoles()) { - RoleAdapter roleAdapter = (RoleAdapter)role; - roleAdapter.removeApplicationComposites(id); - } - - for (RoleModel role : appToBeRemoved.getRoles()) { - appToBeRemoved.removeRole(role); - } - - return (allApps.remove(id) != null); - } - - @Override - public OAuthClientModel addOAuthClient(String name) { - return this.addOAuthClient(KeycloakModelUtils.generateId(), name); - } - - @Override - public OAuthClientModel addOAuthClient(String id, String name) { - if (id == null) throw new NullPointerException("id == null"); - if (name == null) throw new NullPointerException("name == null"); - if (hasOAuthClientWithName(name)) throw new ModelDuplicateException("OAuth Client with name " + name + " already exists."); - OAuthClientEntity oauthClient = new OAuthClientEntity(); - oauthClient.setId(id); - oauthClient.setRealmId(getId()); - oauthClient.setName(name); - - OAuthClientAdapter oAuthClient = new OAuthClientAdapter(session, this, oauthClient); - allOAuthClients.put(id, oAuthClient); - - return oAuthClient; - } - - boolean hasOAuthClientWithName(String name) { - for (OAuthClientAdapter oaClient : allOAuthClients.values()) { - if (oaClient.getName().equals(name)) return true; - } - - return false; - } - - boolean hasOAuthClientWithClientId(String id) { - for (OAuthClientAdapter oaClient : allOAuthClients.values()) { - if (oaClient.getClientId().equals(id)) return true; - } - - return false; - } - - boolean hasUserWithEmail(String email) { - for (UserModel user : inMemoryModel.getUsers(getId())) { - if (user.getEmail() == null) continue; - if (user.getEmail().equals(email)) return true; - } - - return false; - } - - @Override - public boolean removeOAuthClient(String id) { - return allOAuthClients.remove(id) != null; - } - - @Override - public OAuthClientModel getOAuthClient(String name) { - for (OAuthClientAdapter oAuthClient : allOAuthClients.values()) { - if (oAuthClient.getName().equals(name)) return oAuthClient; - } - - return null; - } - - @Override - public OAuthClientModel getOAuthClientById(String id) { - for (OAuthClientAdapter oAuthClient : allOAuthClients.values()) { - if (oAuthClient.getId().equals(id)) return oAuthClient; - } - - return null; - } - - @Override - public List getOAuthClients() { - return new ArrayList(allOAuthClients.values()); - } - - @Override - public void addRequiredCredential(String type) { - if (type == null) throw new NullPointerException("Credential type can not be null"); - - RequiredCredentialModel credentialModel = initRequiredCredentialModel(type); - - List requiredCredList = realm.getRequiredCredentials(); - for (RequiredCredentialEntity cred : requiredCredList) { - if (type.equals(cred.getType())) return; - } - - addRequiredCredential(credentialModel, requiredCredList); - } - - protected void addRequiredCredential(RequiredCredentialModel credentialModel, List persistentCollection) { - RequiredCredentialEntity credEntity = new RequiredCredentialEntity(); - credEntity.setType(credentialModel.getType()); - credEntity.setFormLabel(credentialModel.getFormLabel()); - credEntity.setInput(credentialModel.isInput()); - credEntity.setSecret(credentialModel.isSecret()); - - persistentCollection.add(credEntity); - } - - @Override - public void updateRequiredCredentials(Set creds) { - updateRequiredCredentials(creds, realm.getRequiredCredentials()); - } - - protected void updateRequiredCredentials(Set creds, List credsEntities) { - Set already = new HashSet(); - Set toRemove = new HashSet(); - for (RequiredCredentialEntity entity : credsEntities) { - if (!creds.contains(entity.getType())) { - toRemove.add(entity); - } else { - already.add(entity.getType()); - } - } - for (RequiredCredentialEntity entity : toRemove) { - credsEntities.remove(entity); - } - for (String cred : creds) { - if (!already.contains(cred)) { - RequiredCredentialModel credentialModel = initRequiredCredentialModel(cred); - addRequiredCredential(credentialModel, credsEntities); - } - } - } - - @Override - public List getRequiredCredentials() { - return convertRequiredCredentialEntities(realm.getRequiredCredentials()); - } - - protected List convertRequiredCredentialEntities(Collection credEntities) { - - List result = new ArrayList(); - for (RequiredCredentialEntity entity : credEntities) { - RequiredCredentialModel credentialModel = new RequiredCredentialModel(); - credentialModel.setFormLabel(entity.getFormLabel()); - credentialModel.setInput(entity.isInput()); - credentialModel.setSecret(entity.isSecret()); - credentialModel.setType(entity.getType()); - - result.add(credentialModel); - } - return result; - } - - protected RequiredCredentialModel initRequiredCredentialModel(String type) { - RequiredCredentialModel credentialModel = RequiredCredentialModel.BUILT_IN.get(type); - if (credentialModel == null) { - throw new RuntimeException("Unknown credential type " + type); - } - return credentialModel; - } - - @Override - public Map getBrowserSecurityHeaders() { - return realm.getBrowserSecurityHeaders(); - } - - @Override - public void setBrowserSecurityHeaders(Map headers) { - realm.setBrowserSecurityHeaders(headers); - } - - @Override - public Map getSmtpConfig() { - return realm.getSmtpConfig(); - } - - @Override - public void setSmtpConfig(Map smtpConfig) { - realm.setSmtpConfig(smtpConfig); - } - - @Override - public List getIdentityProviders() { - return new ArrayList(allIdProviders.values()); - } - - @Override - public IdentityProviderModel getIdentityProviderByAlias(String alias) { - for (IdentityProviderModel identityProviderModel : getIdentityProviders()) { - if (identityProviderModel.getAlias().equals(alias)) { - return identityProviderModel; - } - } - - return null; - } - - @Override - public void addIdentityProvider(IdentityProviderModel identityProvider) { - if (identityProvider.getAlias() == null) throw new NullPointerException("identityProvider.getAlias() == null"); - if (identityProvider.getInternalId() == null) identityProvider.setInternalId(KeycloakModelUtils.generateId()); - allIdProviders.put(identityProvider.getInternalId(), identityProvider); - } - - @Override - public void removeIdentityProviderByAlias(String alias) { - for (IdentityProviderModel provider : getIdentityProviders()) { - if (provider.getAlias().equals(alias)) { - allIdProviders.remove(provider.getInternalId()); - break; - } - } - } - - @Override - public void updateIdentityProvider(IdentityProviderModel identityProvider) { - removeIdentityProviderByAlias(identityProvider.getAlias()); - addIdentityProvider(identityProvider); - } - - @Override - public UserFederationProviderModel addUserFederationProvider(String providerName, Map config, int priority, String displayName, int fullSyncPeriod, int changedSyncPeriod, int lastSync) { - UserFederationProviderEntity entity = new UserFederationProviderEntity(); - entity.setId(KeycloakModelUtils.generateId()); - entity.setPriority(priority); - entity.setProviderName(providerName); - entity.setConfig(config); - if (displayName == null) { - displayName = entity.getId(); - } - entity.setDisplayName(displayName); - entity.setFullSyncPeriod(fullSyncPeriod); - entity.setChangedSyncPeriod(changedSyncPeriod); - entity.setLastSync(lastSync); - realm.getUserFederationProviders().add(entity); - - return new UserFederationProviderModel(entity.getId(), providerName, config, priority, displayName, fullSyncPeriod, changedSyncPeriod, lastSync); - } - - @Override - public void removeUserFederationProvider(UserFederationProviderModel provider) { - Iterator it = realm.getUserFederationProviders().iterator(); - while (it.hasNext()) { - UserFederationProviderEntity entity = it.next(); - if (entity.getId().equals(provider.getId())) { - session.users().preRemove(this, new UserFederationProviderModel(entity.getId(), entity.getProviderName(), entity.getConfig(), entity.getPriority(), entity.getDisplayName(), - entity.getFullSyncPeriod(), entity.getChangedSyncPeriod(), entity.getLastSync())); - it.remove(); - } - } - } - - @Override - public void updateUserFederationProvider(UserFederationProviderModel model) { - Iterator it = realm.getUserFederationProviders().iterator(); - while (it.hasNext()) { - UserFederationProviderEntity entity = it.next(); - if (entity.getId().equals(model.getId())) { - entity.setProviderName(model.getProviderName()); - entity.setConfig(model.getConfig()); - entity.setPriority(model.getPriority()); - String displayName = model.getDisplayName(); - if (displayName != null) { - entity.setDisplayName(model.getDisplayName()); - } - entity.setFullSyncPeriod(model.getFullSyncPeriod()); - entity.setChangedSyncPeriod(model.getChangedSyncPeriod()); - entity.setLastSync(model.getLastSync()); - } - } - } - - @Override - public List getUserFederationProviders() { - List entities = realm.getUserFederationProviders(); - List copy = new LinkedList(); - for (UserFederationProviderEntity entity : entities) { - copy.add(entity); - - } - Collections.sort(copy, new Comparator() { - - @Override - public int compare(UserFederationProviderEntity o1, UserFederationProviderEntity o2) { - return o1.getPriority() - o2.getPriority(); - } - - }); - List result = new LinkedList(); - for (UserFederationProviderEntity entity : copy) { - result.add(new UserFederationProviderModel(entity.getId(), entity.getProviderName(), entity.getConfig(), entity.getPriority(), entity.getDisplayName(), - entity.getFullSyncPeriod(), entity.getChangedSyncPeriod(), entity.getLastSync())); - } - - return result; - } - - @Override - public void setUserFederationProviders(List providers) { - List entities = new LinkedList(); - for (UserFederationProviderModel model : providers) { - UserFederationProviderEntity entity = new UserFederationProviderEntity(); - if (model.getId() != null) entity.setId(model.getId()); - else entity.setId(KeycloakModelUtils.generateId()); - entity.setProviderName(model.getProviderName()); - entity.setConfig(model.getConfig()); - entity.setPriority(model.getPriority()); - String displayName = model.getDisplayName(); - if (displayName == null) { - entity.setDisplayName(entity.getId()); - } - entity.setDisplayName(displayName); - entity.setFullSyncPeriod(model.getFullSyncPeriod()); - entity.setChangedSyncPeriod(model.getChangedSyncPeriod()); - entity.setLastSync(model.getLastSync()); - entities.add(entity); - } - - realm.setUserFederationProviders(entities); - } - - @Override - public boolean isEventsEnabled() { - return realm.isEventsEnabled(); - } - - @Override - public void setEventsEnabled(boolean enabled) { - realm.setEventsEnabled(enabled); - } - - @Override - public long getEventsExpiration() { - return realm.getEventsExpiration(); - } - - @Override - public void setEventsExpiration(long expiration) { - realm.setEventsExpiration(expiration); - } - - @Override - public Set getEventsListeners() { - return new HashSet(realm.getEventsListeners()); - } - - @Override - public void setEventsListeners(Set listeners) { - if (listeners != null) { - realm.setEventsListeners(new ArrayList(listeners)); - } else { - realm.setEventsListeners(Collections.EMPTY_LIST); - } - } - - @Override - public Set getEnabledEventTypes() { - return new HashSet(realm.getEnabledEventTypes()); - } - - @Override - public void setEnabledEventTypes(Set enabledEventTypes) { - if (enabledEventTypes != null) { - realm.setEnabledEventTypes(new ArrayList(enabledEventTypes)); - } else { - realm.setEnabledEventTypes(Collections.EMPTY_LIST); - } - } - - @Override - public ApplicationModel getMasterAdminApp() { - return this.masterAdminApp; - } - - @Override - public void setMasterAdminApp(ApplicationModel app) { - if (app == null) { - realm.setAdminAppId(null); - this.masterAdminApp = null; - } else { - String appId = app.getId(); - if (appId == null) { - throw new IllegalStateException("Master Admin app not initialized."); - } - realm.setAdminAppId(appId); - this.masterAdminApp = app; - } - } - - @Override - public boolean isIdentityFederationEnabled() { - //TODO: not sure if we will support identity federation storage for file - return getIdentityProviders() != null && !getIdentityProviders().isEmpty(); - } - - @Override - public int getAccessCodeLifespanLogin() { - return realm.getAccessCodeLifespanLogin(); - } - - @Override - public void setAccessCodeLifespanLogin(int accessCodeLifespanLogin) { - realm.setAccessCodeLifespanLogin(accessCodeLifespanLogin); - } - - @Override - public boolean isInternationalizationEnabled() { - return realm.isInternationalizationEnabled(); - } - - @Override - public void setInternationalizationEnabled(boolean enabled) { - realm.setInternationalizationEnabled(enabled); - } - - @Override - public Set getSupportedLocales() { - return new HashSet<>(realm.getSupportedLocales()); - } - - @Override - public void setSupportedLocales(Set locales) { - realm.setSupportedLocales(new ArrayList<>(locales)); - } - - @Override - public String getDefaultLocale() { - return realm.getDefaultLocale(); - } - - @Override - public void setDefaultLocale(String locale) { - realm.setDefaultLocale(locale); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || !(o instanceof RealmModel)) return false; - - RealmModel that = (RealmModel) o; - return that.getId().equals(getId()); - } - - @Override - public int hashCode() { - return getId().hashCode(); - } - - @Override - public Set getIdentityProviderMappers() { - Set mappings = new HashSet<>(); - for (IdentityProviderMapperEntity entity : this.realm.getIdentityProviderMappers()) { - IdentityProviderMapperModel mapping = new IdentityProviderMapperModel(); - mapping.setId(entity.getId()); - mapping.setName(entity.getName()); - mapping.setIdentityProviderAlias(entity.getIdentityProviderAlias()); - mapping.setIdentityProviderMapper(entity.getIdentityProviderMapper()); - Map config = new HashMap(); - if (entity.getConfig() != null) { - config.putAll(entity.getConfig()); - } - mapping.setConfig(config); - mappings.add(mapping); - } - return mappings; - } - @Override - public Set getIdentityProviderMappersByAlias(String brokerAlias) { - Set mappings = new HashSet<>(); - for (IdentityProviderMapperEntity entity : this.realm.getIdentityProviderMappers()) { - if (!entity.getIdentityProviderAlias().equals(brokerAlias)) { - continue; - } - IdentityProviderMapperModel mapping = new IdentityProviderMapperModel(); - mapping.setId(entity.getId()); - mapping.setName(entity.getName()); - mapping.setIdentityProviderAlias(entity.getIdentityProviderAlias()); - mapping.setIdentityProviderMapper(entity.getIdentityProviderMapper()); - Map config = new HashMap(); - if (entity.getConfig() != null) { - config.putAll(entity.getConfig()); - } - mapping.setConfig(config); - mappings.add(mapping); - } - return mappings; - } - - @Override - public IdentityProviderMapperModel addIdentityProviderMapper(IdentityProviderMapperModel model) { - if (getIdentityProviderMapperByName(model.getIdentityProviderAlias(), model.getIdentityProviderMapper()) != null) { - throw new RuntimeException("protocol mapper name must be unique per protocol"); - } - String id = KeycloakModelUtils.generateId(); - IdentityProviderMapperEntity entity = new IdentityProviderMapperEntity(); - entity.setId(id); - entity.setName(model.getName()); - entity.setIdentityProviderAlias(model.getIdentityProviderAlias()); - entity.setIdentityProviderMapper(model.getIdentityProviderMapper()); - entity.setConfig(model.getConfig()); - - this.realm.getIdentityProviderMappers().add(entity); - return entityToModel(entity); - } - - protected IdentityProviderMapperEntity getIdentityProviderMapperEntity(String id) { - for (IdentityProviderMapperEntity entity : this.realm.getIdentityProviderMappers()) { - if (entity.getId().equals(id)) { - return entity; - } - } - return null; - - } - - protected IdentityProviderMapperEntity getIdentityProviderMapperEntityByName(String alias, String name) { - for (IdentityProviderMapperEntity entity : this.realm.getIdentityProviderMappers()) { - if (entity.getIdentityProviderAlias().equals(alias) && entity.getName().equals(name)) { - return entity; - } - } - return null; - - } - - @Override - public void removeIdentityProviderMapper(IdentityProviderMapperModel mapping) { - IdentityProviderMapperEntity toDelete = getIdentityProviderMapperEntity(mapping.getId()); - if (toDelete != null) { - this.realm.getIdentityProviderMappers().remove(toDelete); - } - - } - - @Override - public void updateIdentityProviderMapper(IdentityProviderMapperModel mapping) { - IdentityProviderMapperEntity entity = getIdentityProviderMapperEntity(mapping.getId()); - entity.setIdentityProviderAlias(mapping.getIdentityProviderAlias()); - entity.setIdentityProviderMapper(mapping.getIdentityProviderMapper()); - if (entity.getConfig() == null) { - entity.setConfig(mapping.getConfig()); - } else { - entity.getConfig().clear(); - entity.getConfig().putAll(mapping.getConfig()); - } - - } - - @Override - public IdentityProviderMapperModel getIdentityProviderMapperById(String id) { - IdentityProviderMapperEntity entity = getIdentityProviderMapperEntity(id); - if (entity == null) return null; - return entityToModel(entity); - } - - @Override - public IdentityProviderMapperModel getIdentityProviderMapperByName(String alias, String name) { - IdentityProviderMapperEntity entity = getIdentityProviderMapperEntityByName(alias, name); - if (entity == null) return null; - return entityToModel(entity); - } - - protected IdentityProviderMapperModel entityToModel(IdentityProviderMapperEntity entity) { - IdentityProviderMapperModel mapping = new IdentityProviderMapperModel(); - mapping.setId(entity.getId()); - mapping.setName(entity.getName()); - mapping.setIdentityProviderAlias(entity.getIdentityProviderAlias()); - mapping.setIdentityProviderMapper(entity.getIdentityProviderMapper()); - Map config = new HashMap(); - if (entity.getConfig() != null) config.putAll(entity.getConfig()); - mapping.setConfig(config); - return mapping; - } - -} +/* + * Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @author tags. All rights reserved. + * + * 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.file.adapter; + +import org.keycloak.connections.file.InMemoryModel; +import org.keycloak.enums.SslRequired; +import org.keycloak.models.ClientModel; +import org.keycloak.models.IdentityProviderMapperModel; +import org.keycloak.models.IdentityProviderModel; +import org.keycloak.models.KeycloakSession; +import org.keycloak.models.ModelDuplicateException; +import org.keycloak.models.PasswordPolicy; +import org.keycloak.models.RealmModel; +import org.keycloak.models.RequiredCredentialModel; +import org.keycloak.models.RoleModel; +import org.keycloak.models.UserFederationProviderModel; +import org.keycloak.models.UserModel; +import org.keycloak.models.entities.ClientEntity; +import org.keycloak.models.entities.IdentityProviderMapperEntity; +import org.keycloak.models.entities.RealmEntity; +import org.keycloak.models.entities.RequiredCredentialEntity; +import org.keycloak.models.entities.RoleEntity; +import org.keycloak.models.entities.UserFederationProviderEntity; +import org.keycloak.models.utils.KeycloakModelUtils; + +import java.security.Key; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * RealmModel for JSON persistence. + * + * @author Stan Silvert ssilvert@redhat.com (C) 2015 Red Hat Inc. + */ +public class RealmAdapter implements RealmModel { + + private final InMemoryModel inMemoryModel; + private final RealmEntity realm; + + protected volatile transient PublicKey publicKey; + protected volatile transient PrivateKey privateKey; + protected volatile transient X509Certificate certificate; + protected volatile transient Key codeSecretKey; + + private volatile transient PasswordPolicy passwordPolicy; + private volatile transient KeycloakSession session; + + private final Map allApps = new HashMap(); + private ClientModel masterAdminApp = null; + private final Map allRoles = new HashMap(); + private final Map allIdProviders = new HashMap(); + + public RealmAdapter(KeycloakSession session, RealmEntity realm, InMemoryModel inMemoryModel) { + this.session = session; + this.realm = realm; + this.inMemoryModel = inMemoryModel; + } + + public RealmEntity getRealmEnity() { + return realm; + } + + @Override + public String getId() { + return realm.getId(); + } + + @Override + public String getName() { + return realm.getName(); + } + + @Override + public void setName(String name) { + if (getName() == null) { + realm.setName(name); + return; + } + + if (getName().equals(name)) return; // allow setting name to same value + + if (inMemoryModel.getRealmByName(name) != null) throw new ModelDuplicateException("Realm " + name + " already exists."); + realm.setName(name); + } + + @Override + public boolean isEnabled() { + return realm.isEnabled(); + } + + @Override + public void setEnabled(boolean enabled) { + realm.setEnabled(enabled); + } + + @Override + public SslRequired getSslRequired() { + return SslRequired.valueOf(realm.getSslRequired()); + } + + @Override + public void setSslRequired(SslRequired sslRequired) { + realm.setSslRequired(sslRequired.name()); + } + + @Override + public boolean isPasswordCredentialGrantAllowed() { + return realm.isPasswordCredentialGrantAllowed(); + } + + @Override + public void setPasswordCredentialGrantAllowed(boolean passwordCredentialGrantAllowed) { + realm.setPasswordCredentialGrantAllowed(passwordCredentialGrantAllowed); + } + + @Override + public boolean isRegistrationAllowed() { + return realm.isRegistrationAllowed(); + } + + @Override + public void setRegistrationAllowed(boolean registrationAllowed) { + realm.setRegistrationAllowed(registrationAllowed); + } + + @Override + public boolean isRegistrationEmailAsUsername() { + return realm.isRegistrationEmailAsUsername(); + } + + @Override + public void setRegistrationEmailAsUsername(boolean registrationEmailAsUsername) { + realm.setRegistrationEmailAsUsername(registrationEmailAsUsername); + } + + @Override + public boolean isRememberMe() { + return realm.isRememberMe(); + } + + @Override + public void setRememberMe(boolean rememberMe) { + realm.setRememberMe(rememberMe); + } + + @Override + public boolean isBruteForceProtected() { + return realm.isBruteForceProtected(); + } + + @Override + public void setBruteForceProtected(boolean value) { + realm.setBruteForceProtected(value); + } + + @Override + public int getMaxFailureWaitSeconds() { + return realm.getMaxFailureWaitSeconds(); + } + + @Override + public void setMaxFailureWaitSeconds(int val) { + realm.setMaxFailureWaitSeconds(val); + } + + @Override + public int getWaitIncrementSeconds() { + return realm.getWaitIncrementSeconds(); + } + + @Override + public void setWaitIncrementSeconds(int val) { + realm.setWaitIncrementSeconds(val); + } + + @Override + public long getQuickLoginCheckMilliSeconds() { + return realm.getQuickLoginCheckMilliSeconds(); + } + + @Override + public void setQuickLoginCheckMilliSeconds(long val) { + realm.setQuickLoginCheckMilliSeconds(val); + } + + @Override + public int getMinimumQuickLoginWaitSeconds() { + return realm.getMinimumQuickLoginWaitSeconds(); + } + + @Override + public void setMinimumQuickLoginWaitSeconds(int val) { + realm.setMinimumQuickLoginWaitSeconds(val); + } + + + @Override + public int getMaxDeltaTimeSeconds() { + return realm.getMaxDeltaTimeSeconds(); + } + + @Override + public void setMaxDeltaTimeSeconds(int val) { + realm.setMaxDeltaTimeSeconds(val); + } + + @Override + public int getFailureFactor() { + return realm.getFailureFactor(); + } + + @Override + public void setFailureFactor(int failureFactor) { + realm.setFailureFactor(failureFactor); + } + + + @Override + public boolean isVerifyEmail() { + return realm.isVerifyEmail(); + } + + @Override + public void setVerifyEmail(boolean verifyEmail) { + realm.setVerifyEmail(verifyEmail); + } + + @Override + public boolean isResetPasswordAllowed() { + return realm.isResetPasswordAllowed(); + } + + @Override + public void setResetPasswordAllowed(boolean resetPassword) { + realm.setResetPasswordAllowed(resetPassword); + } + + @Override + public PasswordPolicy getPasswordPolicy() { + if (passwordPolicy == null) { + passwordPolicy = new PasswordPolicy(realm.getPasswordPolicy()); + } + return passwordPolicy; + } + + @Override + public void setPasswordPolicy(PasswordPolicy policy) { + this.passwordPolicy = policy; + realm.setPasswordPolicy(policy.toString()); + } + + @Override + public int getNotBefore() { + return realm.getNotBefore(); + } + + @Override + public void setNotBefore(int notBefore) { + realm.setNotBefore(notBefore); + } + + + @Override + public int getSsoSessionIdleTimeout() { + return realm.getSsoSessionIdleTimeout(); + } + + @Override + public void setSsoSessionIdleTimeout(int seconds) { + realm.setSsoSessionIdleTimeout(seconds); + } + + @Override + public int getSsoSessionMaxLifespan() { + return realm.getSsoSessionMaxLifespan(); + } + + @Override + public void setSsoSessionMaxLifespan(int seconds) { + realm.setSsoSessionMaxLifespan(seconds); + } + + @Override + public int getAccessTokenLifespan() { + return realm.getAccessTokenLifespan(); + } + + @Override + public void setAccessTokenLifespan(int tokenLifespan) { + realm.setAccessTokenLifespan(tokenLifespan); + } + + @Override + public int getAccessCodeLifespan() { + return realm.getAccessCodeLifespan(); + } + + @Override + public void setAccessCodeLifespan(int accessCodeLifespan) { + realm.setAccessCodeLifespan(accessCodeLifespan); + } + + @Override + public int getAccessCodeLifespanUserAction() { + return realm.getAccessCodeLifespanUserAction(); + } + + @Override + public void setAccessCodeLifespanUserAction(int accessCodeLifespanUserAction) { + realm.setAccessCodeLifespanUserAction(accessCodeLifespanUserAction); + } + + @Override + public String getPublicKeyPem() { + return realm.getPublicKeyPem(); + } + + @Override + public void setPublicKeyPem(String publicKeyPem) { + realm.setPublicKeyPem(publicKeyPem); + this.publicKey = null; + } + + @Override + public X509Certificate getCertificate() { + if (certificate != null) return certificate; + certificate = KeycloakModelUtils.getCertificate(getCertificatePem()); + return certificate; + } + + @Override + public void setCertificate(X509Certificate certificate) { + this.certificate = certificate; + String certificatePem = KeycloakModelUtils.getPemFromCertificate(certificate); + setCertificatePem(certificatePem); + } + + @Override + public String getCertificatePem() { + return realm.getCertificatePem(); + } + + @Override + public void setCertificatePem(String certificate) { + realm.setCertificatePem(certificate); + + } + + + @Override + public String getPrivateKeyPem() { + return realm.getPrivateKeyPem(); + } + + @Override + public void setPrivateKeyPem(String privateKeyPem) { + realm.setPrivateKeyPem(privateKeyPem); + this.privateKey = null; + } + + @Override + public PublicKey getPublicKey() { + if (publicKey != null) return publicKey; + publicKey = KeycloakModelUtils.getPublicKey(getPublicKeyPem()); + return publicKey; + } + + @Override + public void setPublicKey(PublicKey publicKey) { + this.publicKey = publicKey; + String publicKeyPem = KeycloakModelUtils.getPemFromKey(publicKey); + setPublicKeyPem(publicKeyPem); + } + + @Override + public PrivateKey getPrivateKey() { + if (privateKey != null) return privateKey; + privateKey = KeycloakModelUtils.getPrivateKey(getPrivateKeyPem()); + return privateKey; + } + + @Override + public void setPrivateKey(PrivateKey privateKey) { + this.privateKey = privateKey; + String privateKeyPem = KeycloakModelUtils.getPemFromKey(privateKey); + setPrivateKeyPem(privateKeyPem); + } + + @Override + public String getCodeSecret() { + return realm.getCodeSecret(); + } + + @Override + public Key getCodeSecretKey() { + if (codeSecretKey == null) { + codeSecretKey = KeycloakModelUtils.getSecretKey(getCodeSecret()); + } + return codeSecretKey; + } + + @Override + public void setCodeSecret(String codeSecret) { + realm.setCodeSecret(codeSecret); + } + + @Override + public String getLoginTheme() { + return realm.getLoginTheme(); + } + + @Override + public void setLoginTheme(String name) { + realm.setLoginTheme(name); + } + + @Override + public String getAccountTheme() { + return realm.getAccountTheme(); + } + + @Override + public void setAccountTheme(String name) { + realm.setAccountTheme(name); + } + + @Override + public String getAdminTheme() { + return realm.getAdminTheme(); + } + + @Override + public void setAdminTheme(String name) { + realm.setAdminTheme(name); + } + + @Override + public String getEmailTheme() { + return realm.getEmailTheme(); + } + + @Override + public void setEmailTheme(String name) { + realm.setEmailTheme(name); + } + + @Override + public RoleAdapter getRole(String name) { + for (RoleAdapter role : allRoles.values()) { + if (role.getName().equals(name)) return role; + } + return null; + } + + @Override + public RoleModel addRole(String name) { + return this.addRole(KeycloakModelUtils.generateId(), name); + } + + @Override + public RoleModel addRole(String id, String name) { + if (id == null) throw new NullPointerException("id == null"); + if (name == null) throw new NullPointerException("name == null"); + if (hasRoleWithName(name)) throw new ModelDuplicateException("Realm already contains role with name " + name + "."); + + RoleEntity roleEntity = new RoleEntity(); + roleEntity.setId(id); + roleEntity.setName(name); + roleEntity.setRealmId(getId()); + + RoleAdapter roleModel = new RoleAdapter(this, roleEntity, this); + allRoles.put(id, roleModel); + return roleModel; + } + + @Override + public boolean removeRole(RoleModel role) { + return removeRoleById(role.getId()); + } + + @Override + public boolean removeRoleById(String id) { + if (id == null) throw new NullPointerException("id == null"); + + // try realm roles first + if (allRoles.remove(id) != null) return true; + + for (ClientModel app : getClients()) { + for (RoleModel appRole : app.getRoles()) { + if (id.equals(appRole.getId())) { + app.removeRole(appRole); + return true; + } + } + } + + return false; + } + + @Override + public Set getRoles() { + return new HashSet(allRoles.values()); + } + + @Override + public RoleModel getRoleById(String id) { + RoleModel found = allRoles.get(id); + if (found != null) return found; + + for (ClientModel app : getClients()) { + for (RoleModel appRole : app.getRoles()) { + if (appRole.getId().equals(id)) return appRole; + } + } + + return null; + } + + @Override + public List getDefaultRoles() { + return realm.getDefaultRoles(); + } + + @Override + public void addDefaultRole(String name) { + RoleModel role = getRole(name); + if (role == null) { + addRole(name); + } + + List roleNames = getDefaultRoles(); + if (roleNames.contains(name)) throw new IllegalArgumentException("Realm " + realm.getName() + " already contains default role named " + name); + + roleNames.add(name); + realm.setDefaultRoles(roleNames); + } + + boolean hasRoleWithName(String name) { + for (RoleModel role : allRoles.values()) { + if (role.getName().equals(name)) return true; + } + + return false; + } + + @Override + public void updateDefaultRoles(String[] defaultRoles) { + List roleNames = new ArrayList(); + for (String roleName : defaultRoles) { + RoleModel role = getRole(roleName); + if (role == null) { + addRole(roleName); + } + + roleNames.add(roleName); + } + + realm.setDefaultRoles(roleNames); + } + + @Override + public ClientModel getClientById(String id) { + return allApps.get(id); + } + + @Override + public ClientModel getClientByClientId(String clientId) { + for (ClientModel app : getClients()) { + if (app.getClientId().equals(clientId)) return app; + } + + return null; + } + + @Override + public Map getClientNameMap() { + Map resourceMap = new HashMap(); + for (ClientModel resource : getClients()) { + resourceMap.put(resource.getClientId(), resource); + } + return resourceMap; + } + + @Override + public List getClients() { + return new ArrayList(allApps.values()); + } + + @Override + public ClientModel addClient(String name) { + return this.addClient(KeycloakModelUtils.generateId(), name); + } + + @Override + public ClientModel addClient(String id, String clientId) { + if (clientId == null) throw new NullPointerException("name == null"); + if (id == null) throw new NullPointerException("id == null"); + + if (getClientNameMap().containsKey(clientId)) { + throw new ModelDuplicateException("Application named '" + clientId + "' already exists."); + } + + ClientEntity appEntity = new ClientEntity(); + appEntity.setId(id); + appEntity.setClientId(clientId); + appEntity.setRealmId(getId()); + appEntity.setEnabled(true); + + final ClientModel app = new ClientAdapter(session, this, appEntity, inMemoryModel); + session.getKeycloakSessionFactory().publish(new ClientCreationEvent() { + @Override + public ClientModel getCreatedClient() { + return app; + } + }); + + allApps.put(id, app); + + return app; + } + + @Override + public boolean removeClient(String id) { + ClientModel appToBeRemoved = this.getClientById(id); + if (appToBeRemoved == null) return false; + + // remove any composite role assignments for this app + for (RoleModel role : this.getRoles()) { + RoleAdapter roleAdapter = (RoleAdapter)role; + roleAdapter.removeApplicationComposites(id); + } + + for (RoleModel role : appToBeRemoved.getRoles()) { + appToBeRemoved.removeRole(role); + } + + return (allApps.remove(id) != null); + } + + boolean hasUserWithEmail(String email) { + for (UserModel user : inMemoryModel.getUsers(getId())) { + if (user.getEmail() == null) continue; + if (user.getEmail().equals(email)) return true; + } + + return false; + } + + @Override + public void addRequiredCredential(String type) { + if (type == null) throw new NullPointerException("Credential type can not be null"); + + RequiredCredentialModel credentialModel = initRequiredCredentialModel(type); + + List requiredCredList = realm.getRequiredCredentials(); + for (RequiredCredentialEntity cred : requiredCredList) { + if (type.equals(cred.getType())) return; + } + + addRequiredCredential(credentialModel, requiredCredList); + } + + protected void addRequiredCredential(RequiredCredentialModel credentialModel, List persistentCollection) { + RequiredCredentialEntity credEntity = new RequiredCredentialEntity(); + credEntity.setType(credentialModel.getType()); + credEntity.setFormLabel(credentialModel.getFormLabel()); + credEntity.setInput(credentialModel.isInput()); + credEntity.setSecret(credentialModel.isSecret()); + + persistentCollection.add(credEntity); + } + + @Override + public void updateRequiredCredentials(Set creds) { + updateRequiredCredentials(creds, realm.getRequiredCredentials()); + } + + protected void updateRequiredCredentials(Set creds, List credsEntities) { + Set already = new HashSet(); + Set toRemove = new HashSet(); + for (RequiredCredentialEntity entity : credsEntities) { + if (!creds.contains(entity.getType())) { + toRemove.add(entity); + } else { + already.add(entity.getType()); + } + } + for (RequiredCredentialEntity entity : toRemove) { + credsEntities.remove(entity); + } + for (String cred : creds) { + if (!already.contains(cred)) { + RequiredCredentialModel credentialModel = initRequiredCredentialModel(cred); + addRequiredCredential(credentialModel, credsEntities); + } + } + } + + @Override + public List getRequiredCredentials() { + return convertRequiredCredentialEntities(realm.getRequiredCredentials()); + } + + protected List convertRequiredCredentialEntities(Collection credEntities) { + + List result = new ArrayList(); + for (RequiredCredentialEntity entity : credEntities) { + RequiredCredentialModel credentialModel = new RequiredCredentialModel(); + credentialModel.setFormLabel(entity.getFormLabel()); + credentialModel.setInput(entity.isInput()); + credentialModel.setSecret(entity.isSecret()); + credentialModel.setType(entity.getType()); + + result.add(credentialModel); + } + return result; + } + + protected RequiredCredentialModel initRequiredCredentialModel(String type) { + RequiredCredentialModel credentialModel = RequiredCredentialModel.BUILT_IN.get(type); + if (credentialModel == null) { + throw new RuntimeException("Unknown credential type " + type); + } + return credentialModel; + } + + @Override + public Map getBrowserSecurityHeaders() { + return realm.getBrowserSecurityHeaders(); + } + + @Override + public void setBrowserSecurityHeaders(Map headers) { + realm.setBrowserSecurityHeaders(headers); + } + + @Override + public Map getSmtpConfig() { + return realm.getSmtpConfig(); + } + + @Override + public void setSmtpConfig(Map smtpConfig) { + realm.setSmtpConfig(smtpConfig); + } + + @Override + public List getIdentityProviders() { + return new ArrayList(allIdProviders.values()); + } + + @Override + public IdentityProviderModel getIdentityProviderByAlias(String alias) { + for (IdentityProviderModel identityProviderModel : getIdentityProviders()) { + if (identityProviderModel.getAlias().equals(alias)) { + return identityProviderModel; + } + } + + return null; + } + + @Override + public void addIdentityProvider(IdentityProviderModel identityProvider) { + if (identityProvider.getAlias() == null) throw new NullPointerException("identityProvider.getAlias() == null"); + if (identityProvider.getInternalId() == null) identityProvider.setInternalId(KeycloakModelUtils.generateId()); + allIdProviders.put(identityProvider.getInternalId(), identityProvider); + } + + @Override + public void removeIdentityProviderByAlias(String alias) { + for (IdentityProviderModel provider : getIdentityProviders()) { + if (provider.getAlias().equals(alias)) { + allIdProviders.remove(provider.getInternalId()); + break; + } + } + } + + @Override + public void updateIdentityProvider(IdentityProviderModel identityProvider) { + removeIdentityProviderByAlias(identityProvider.getAlias()); + addIdentityProvider(identityProvider); + } + + @Override + public UserFederationProviderModel addUserFederationProvider(String providerName, Map config, int priority, String displayName, int fullSyncPeriod, int changedSyncPeriod, int lastSync) { + UserFederationProviderEntity entity = new UserFederationProviderEntity(); + entity.setId(KeycloakModelUtils.generateId()); + entity.setPriority(priority); + entity.setProviderName(providerName); + entity.setConfig(config); + if (displayName == null) { + displayName = entity.getId(); + } + entity.setDisplayName(displayName); + entity.setFullSyncPeriod(fullSyncPeriod); + entity.setChangedSyncPeriod(changedSyncPeriod); + entity.setLastSync(lastSync); + realm.getUserFederationProviders().add(entity); + + return new UserFederationProviderModel(entity.getId(), providerName, config, priority, displayName, fullSyncPeriod, changedSyncPeriod, lastSync); + } + + @Override + public void removeUserFederationProvider(UserFederationProviderModel provider) { + Iterator it = realm.getUserFederationProviders().iterator(); + while (it.hasNext()) { + UserFederationProviderEntity entity = it.next(); + if (entity.getId().equals(provider.getId())) { + session.users().preRemove(this, new UserFederationProviderModel(entity.getId(), entity.getProviderName(), entity.getConfig(), entity.getPriority(), entity.getDisplayName(), + entity.getFullSyncPeriod(), entity.getChangedSyncPeriod(), entity.getLastSync())); + it.remove(); + } + } + } + + @Override + public void updateUserFederationProvider(UserFederationProviderModel model) { + Iterator it = realm.getUserFederationProviders().iterator(); + while (it.hasNext()) { + UserFederationProviderEntity entity = it.next(); + if (entity.getId().equals(model.getId())) { + entity.setProviderName(model.getProviderName()); + entity.setConfig(model.getConfig()); + entity.setPriority(model.getPriority()); + String displayName = model.getDisplayName(); + if (displayName != null) { + entity.setDisplayName(model.getDisplayName()); + } + entity.setFullSyncPeriod(model.getFullSyncPeriod()); + entity.setChangedSyncPeriod(model.getChangedSyncPeriod()); + entity.setLastSync(model.getLastSync()); + } + } + } + + @Override + public List getUserFederationProviders() { + List entities = realm.getUserFederationProviders(); + List copy = new LinkedList(); + for (UserFederationProviderEntity entity : entities) { + copy.add(entity); + + } + Collections.sort(copy, new Comparator() { + + @Override + public int compare(UserFederationProviderEntity o1, UserFederationProviderEntity o2) { + return o1.getPriority() - o2.getPriority(); + } + + }); + List result = new LinkedList(); + for (UserFederationProviderEntity entity : copy) { + result.add(new UserFederationProviderModel(entity.getId(), entity.getProviderName(), entity.getConfig(), entity.getPriority(), entity.getDisplayName(), + entity.getFullSyncPeriod(), entity.getChangedSyncPeriod(), entity.getLastSync())); + } + + return result; + } + + @Override + public void setUserFederationProviders(List providers) { + List entities = new LinkedList(); + for (UserFederationProviderModel model : providers) { + UserFederationProviderEntity entity = new UserFederationProviderEntity(); + if (model.getId() != null) entity.setId(model.getId()); + else entity.setId(KeycloakModelUtils.generateId()); + entity.setProviderName(model.getProviderName()); + entity.setConfig(model.getConfig()); + entity.setPriority(model.getPriority()); + String displayName = model.getDisplayName(); + if (displayName == null) { + entity.setDisplayName(entity.getId()); + } + entity.setDisplayName(displayName); + entity.setFullSyncPeriod(model.getFullSyncPeriod()); + entity.setChangedSyncPeriod(model.getChangedSyncPeriod()); + entity.setLastSync(model.getLastSync()); + entities.add(entity); + } + + realm.setUserFederationProviders(entities); + } + + @Override + public boolean isEventsEnabled() { + return realm.isEventsEnabled(); + } + + @Override + public void setEventsEnabled(boolean enabled) { + realm.setEventsEnabled(enabled); + } + + @Override + public long getEventsExpiration() { + return realm.getEventsExpiration(); + } + + @Override + public void setEventsExpiration(long expiration) { + realm.setEventsExpiration(expiration); + } + + @Override + public Set getEventsListeners() { + return new HashSet(realm.getEventsListeners()); + } + + @Override + public void setEventsListeners(Set listeners) { + if (listeners != null) { + realm.setEventsListeners(new ArrayList(listeners)); + } else { + realm.setEventsListeners(Collections.EMPTY_LIST); + } + } + + @Override + public Set getEnabledEventTypes() { + return new HashSet(realm.getEnabledEventTypes()); + } + + @Override + public void setEnabledEventTypes(Set enabledEventTypes) { + if (enabledEventTypes != null) { + realm.setEnabledEventTypes(new ArrayList(enabledEventTypes)); + } else { + realm.setEnabledEventTypes(Collections.EMPTY_LIST); + } + } + + @Override + public ClientModel getMasterAdminClient() { + return this.masterAdminApp; + } + + @Override + public void setMasterAdminClient(ClientModel client) { + if (client == null) { + realm.setAdminAppId(null); + this.masterAdminApp = null; + } else { + String appId = client.getId(); + if (appId == null) { + throw new IllegalStateException("Master Admin app not initialized."); + } + realm.setAdminAppId(appId); + this.masterAdminApp = client; + } + } + + @Override + public boolean isIdentityFederationEnabled() { + //TODO: not sure if we will support identity federation storage for file + return getIdentityProviders() != null && !getIdentityProviders().isEmpty(); + } + + @Override + public int getAccessCodeLifespanLogin() { + return realm.getAccessCodeLifespanLogin(); + } + + @Override + public void setAccessCodeLifespanLogin(int accessCodeLifespanLogin) { + realm.setAccessCodeLifespanLogin(accessCodeLifespanLogin); + } + + @Override + public boolean isInternationalizationEnabled() { + return realm.isInternationalizationEnabled(); + } + + @Override + public void setInternationalizationEnabled(boolean enabled) { + realm.setInternationalizationEnabled(enabled); + } + + @Override + public Set getSupportedLocales() { + return new HashSet<>(realm.getSupportedLocales()); + } + + @Override + public void setSupportedLocales(Set locales) { + realm.setSupportedLocales(new ArrayList<>(locales)); + } + + @Override + public String getDefaultLocale() { + return realm.getDefaultLocale(); + } + + @Override + public void setDefaultLocale(String locale) { + realm.setDefaultLocale(locale); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || !(o instanceof RealmModel)) return false; + + RealmModel that = (RealmModel) o; + return that.getId().equals(getId()); + } + + @Override + public int hashCode() { + return getId().hashCode(); + } + + @Override + public Set getIdentityProviderMappers() { + Set mappings = new HashSet<>(); + for (IdentityProviderMapperEntity entity : this.realm.getIdentityProviderMappers()) { + IdentityProviderMapperModel mapping = new IdentityProviderMapperModel(); + mapping.setId(entity.getId()); + mapping.setName(entity.getName()); + mapping.setIdentityProviderAlias(entity.getIdentityProviderAlias()); + mapping.setIdentityProviderMapper(entity.getIdentityProviderMapper()); + Map config = new HashMap(); + if (entity.getConfig() != null) { + config.putAll(entity.getConfig()); + } + mapping.setConfig(config); + mappings.add(mapping); + } + return mappings; + } + @Override + public Set getIdentityProviderMappersByAlias(String brokerAlias) { + Set mappings = new HashSet<>(); + for (IdentityProviderMapperEntity entity : this.realm.getIdentityProviderMappers()) { + if (!entity.getIdentityProviderAlias().equals(brokerAlias)) { + continue; + } + IdentityProviderMapperModel mapping = new IdentityProviderMapperModel(); + mapping.setId(entity.getId()); + mapping.setName(entity.getName()); + mapping.setIdentityProviderAlias(entity.getIdentityProviderAlias()); + mapping.setIdentityProviderMapper(entity.getIdentityProviderMapper()); + Map config = new HashMap(); + if (entity.getConfig() != null) { + config.putAll(entity.getConfig()); + } + mapping.setConfig(config); + mappings.add(mapping); + } + return mappings; + } + + @Override + public IdentityProviderMapperModel addIdentityProviderMapper(IdentityProviderMapperModel model) { + if (getIdentityProviderMapperByName(model.getIdentityProviderAlias(), model.getIdentityProviderMapper()) != null) { + throw new RuntimeException("protocol mapper name must be unique per protocol"); + } + String id = KeycloakModelUtils.generateId(); + IdentityProviderMapperEntity entity = new IdentityProviderMapperEntity(); + entity.setId(id); + entity.setName(model.getName()); + entity.setIdentityProviderAlias(model.getIdentityProviderAlias()); + entity.setIdentityProviderMapper(model.getIdentityProviderMapper()); + entity.setConfig(model.getConfig()); + + this.realm.getIdentityProviderMappers().add(entity); + return entityToModel(entity); + } + + protected IdentityProviderMapperEntity getIdentityProviderMapperEntity(String id) { + for (IdentityProviderMapperEntity entity : this.realm.getIdentityProviderMappers()) { + if (entity.getId().equals(id)) { + return entity; + } + } + return null; + + } + + protected IdentityProviderMapperEntity getIdentityProviderMapperEntityByName(String alias, String name) { + for (IdentityProviderMapperEntity entity : this.realm.getIdentityProviderMappers()) { + if (entity.getIdentityProviderAlias().equals(alias) && entity.getName().equals(name)) { + return entity; + } + } + return null; + + } + + @Override + public void removeIdentityProviderMapper(IdentityProviderMapperModel mapping) { + IdentityProviderMapperEntity toDelete = getIdentityProviderMapperEntity(mapping.getId()); + if (toDelete != null) { + this.realm.getIdentityProviderMappers().remove(toDelete); + } + + } + + @Override + public void updateIdentityProviderMapper(IdentityProviderMapperModel mapping) { + IdentityProviderMapperEntity entity = getIdentityProviderMapperEntity(mapping.getId()); + entity.setIdentityProviderAlias(mapping.getIdentityProviderAlias()); + entity.setIdentityProviderMapper(mapping.getIdentityProviderMapper()); + if (entity.getConfig() == null) { + entity.setConfig(mapping.getConfig()); + } else { + entity.getConfig().clear(); + entity.getConfig().putAll(mapping.getConfig()); + } + + } + + @Override + public IdentityProviderMapperModel getIdentityProviderMapperById(String id) { + IdentityProviderMapperEntity entity = getIdentityProviderMapperEntity(id); + if (entity == null) return null; + return entityToModel(entity); + } + + @Override + public IdentityProviderMapperModel getIdentityProviderMapperByName(String alias, String name) { + IdentityProviderMapperEntity entity = getIdentityProviderMapperEntityByName(alias, name); + if (entity == null) return null; + return entityToModel(entity); + } + + protected IdentityProviderMapperModel entityToModel(IdentityProviderMapperEntity entity) { + IdentityProviderMapperModel mapping = new IdentityProviderMapperModel(); + mapping.setId(entity.getId()); + mapping.setName(entity.getName()); + mapping.setIdentityProviderAlias(entity.getIdentityProviderAlias()); + mapping.setIdentityProviderMapper(entity.getIdentityProviderMapper()); + Map config = new HashMap(); + if (entity.getConfig() != null) config.putAll(entity.getConfig()); + mapping.setConfig(config); + return mapping; + } + +} diff --git a/model/file/src/main/java/org/keycloak/models/file/adapter/RoleAdapter.java b/model/file/src/main/java/org/keycloak/models/file/adapter/RoleAdapter.java index 28a2f9001c..f53c0ce68e 100755 --- a/model/file/src/main/java/org/keycloak/models/file/adapter/RoleAdapter.java +++ b/model/file/src/main/java/org/keycloak/models/file/adapter/RoleAdapter.java @@ -111,7 +111,7 @@ public class RoleAdapter implements RoleModel { Set toBeRemoved = new HashSet(); for (RoleModel compositeRole : getComposites()) { RoleAdapter roleAdapter = (RoleAdapter)compositeRole; - if (appId.equals(roleAdapter.getRoleEntity().getApplicationId())) { + if (appId.equals(roleAdapter.getRoleEntity().getClientId())) { toBeRemoved.add(compositeRole); } else { roleAdapter.removeApplicationComposites(appId); @@ -143,8 +143,8 @@ public class RoleAdapter implements RoleModel { // Compute it if (role.getRealmId() != null) { roleContainer = realm;//new RealmAdapter(session, realm); - } else if (role.getApplicationId() != null) { - roleContainer = realm.getApplicationById(role.getApplicationId());//new ApplicationAdapter(session, realm, appEntity); + } else if (role.getClientId() != null) { + roleContainer = realm.getClientById(role.getClientId());//new ApplicationAdapter(session, realm, appEntity); } else { throw new IllegalStateException("Both realmId and applicationId are null for role: " + this); } diff --git a/model/file/src/main/java/org/keycloak/models/file/adapter/UserAdapter.java b/model/file/src/main/java/org/keycloak/models/file/adapter/UserAdapter.java index f1a7a28ac9..e9ba84ab01 100755 --- a/model/file/src/main/java/org/keycloak/models/file/adapter/UserAdapter.java +++ b/model/file/src/main/java/org/keycloak/models/file/adapter/UserAdapter.java @@ -16,7 +16,7 @@ */ package org.keycloak.models.file.adapter; -import org.keycloak.models.ApplicationModel; +import org.keycloak.models.ClientModel; import org.keycloak.models.PasswordPolicy; import org.keycloak.models.RealmModel; import org.keycloak.models.RoleModel; @@ -325,12 +325,12 @@ public class UserAdapter implements UserModel, Comparable { } @Override - public Set getApplicationRoleMappings(ApplicationModel app) { + public Set getClientRoleMappings(ClientModel app) { Set result = new HashSet(); for (RoleModel role : allRoles) { RoleEntity roleEntity = ((RoleAdapter)role).getRoleEntity(); - if (app.getId().equals(roleEntity.getApplicationId())) { + if (app.getId().equals(roleEntity.getClientId())) { result.add(new RoleAdapter(realm, roleEntity, app)); } } diff --git a/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanRealmCache.java b/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanRealmCache.java index a01a135273..b5204e8b41 100755 --- a/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanRealmCache.java +++ b/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanRealmCache.java @@ -4,7 +4,6 @@ import org.infinispan.Cache; import org.jboss.logging.Logger; import org.keycloak.models.cache.RealmCache; import org.keycloak.models.cache.entities.CachedApplication; -import org.keycloak.models.cache.entities.CachedOAuthClient; import org.keycloak.models.cache.entities.CachedRealm; import org.keycloak.models.cache.entities.CachedRole; @@ -102,31 +101,6 @@ public class InfinispanRealmCache implements RealmCache { cache.remove(id); } - @Override - public CachedOAuthClient getOAuthClient(String id) { - if (!enabled) return null; - return get(id, CachedOAuthClient.class); - } - - @Override - public void invalidateOAuthClient(CachedOAuthClient client) { - logger.tracev("Removing oauth client {0}", client.getId()); - cache.remove(client.getId()); - } - - @Override - public void addCachedOAuthClient(CachedOAuthClient client) { - if (!enabled) return; - logger.tracev("Adding oauth client {0}", client.getId()); - cache.put(client.getId(), client); - } - - @Override - public void invalidateCachedOAuthClientById(String id) { - logger.tracev("Removing oauth client {0}", id); - cache.remove(id); - } - @Override public CachedRole getRole(String id) { if (!enabled) return null; diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/ApplicationAdapter.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/ApplicationAdapter.java deleted file mode 100755 index fd238811de..0000000000 --- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/ApplicationAdapter.java +++ /dev/null @@ -1,247 +0,0 @@ -package org.keycloak.models.cache; - -import org.keycloak.models.ApplicationModel; -import org.keycloak.models.ClientModel; -import org.keycloak.models.RealmModel; -import org.keycloak.models.RoleContainerModel; -import org.keycloak.models.RoleModel; -import org.keycloak.models.cache.entities.CachedApplication; - -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * @author Bill Burke - * @version $Revision: 1 $ - */ -public class ApplicationAdapter extends ClientAdapter implements ApplicationModel { - protected ApplicationModel updated; - protected CachedApplication cached; - - public ApplicationAdapter(RealmModel cachedRealm, CachedApplication cached, CacheRealmProvider cacheSession, RealmCache cache) { - super(cachedRealm, cached, cache, cacheSession); - this.cached = cached; - } - - @Override - protected void getDelegateForUpdate() { - if (updated == null) { - cacheSession.registerApplicationInvalidation(getId()); - updatedClient = updated = cacheSession.getDelegate().getApplicationById(getId(), cachedRealm); - if (updated == null) throw new IllegalStateException("Not found in database"); - } - } - - @Override - public void updateApplication() { - if (updated != null) updated.updateApplication(); - } - - @Override - public String getName() { - if (updated != null) return updated.getName(); - return cached.getName(); - } - - @Override - public String getClientId() { - return getName(); - } - - @Override - public void setName(String name) { - getDelegateForUpdate(); - updated.setName(name); - cacheSession.registerRealmInvalidation(cachedRealm.getId()); - } - - @Override - public boolean isSurrogateAuthRequired() { - if (updated != null) return updated.isSurrogateAuthRequired(); - return cached.isSurrogateAuthRequired(); - } - - @Override - public void setSurrogateAuthRequired(boolean surrogateAuthRequired) { - getDelegateForUpdate(); - updated.setSurrogateAuthRequired(surrogateAuthRequired); - } - - @Override - public String getManagementUrl() { - if (updated != null) return updated.getManagementUrl(); - return cached.getManagementUrl(); - } - - @Override - public void setManagementUrl(String url) { - getDelegateForUpdate(); - updated.setManagementUrl(url); - } - - @Override - public String getBaseUrl() { - if (updated != null) return updated.getBaseUrl(); - return cached.getBaseUrl(); - } - - @Override - public void setBaseUrl(String url) { - getDelegateForUpdate(); - updated.setBaseUrl(url); - } - - @Override - public List getDefaultRoles() { - if (updated != null) return updated.getDefaultRoles(); - return cached.getDefaultRoles(); - } - - @Override - public void addDefaultRole(String name) { - getDelegateForUpdate(); - updated.addDefaultRole(name); - } - - @Override - public void updateDefaultRoles(String[] defaultRoles) { - getDelegateForUpdate(); - updated.updateDefaultRoles(defaultRoles); - } - - @Override - public Set getApplicationScopeMappings(ClientModel client) { - Set roleMappings = client.getScopeMappings(); - - Set appRoles = new HashSet(); - for (RoleModel role : roleMappings) { - RoleContainerModel container = role.getContainer(); - if (container instanceof RealmModel) { - } else { - ApplicationModel app = (ApplicationModel)container; - if (app.getId().equals(getId())) { - appRoles.add(role); - } - } - } - - return appRoles; - } - - @Override - public boolean isBearerOnly() { - if (updated != null) return updated.isBearerOnly(); - return cached.isBearerOnly(); - } - - @Override - public void setBearerOnly(boolean only) { - getDelegateForUpdate(); - updated.setBearerOnly(only); - } - - @Override - public RoleModel getRole(String name) { - if (updated != null) return updated.getRole(name); - String id = cached.getRoles().get(name); - if (id == null) return null; - return cacheSession.getRoleById(id, cachedRealm); - } - - @Override - public RoleModel addRole(String name) { - getDelegateForUpdate(); - RoleModel role = updated.addRole(name); - cacheSession.registerRoleInvalidation(role.getId()); - return role; - } - - @Override - public RoleModel addRole(String id, String name) { - getDelegateForUpdate(); - RoleModel role = updated.addRole(id, name); - cacheSession.registerRoleInvalidation(role.getId()); - return role; - } - - @Override - public boolean removeRole(RoleModel role) { - cacheSession.registerRoleInvalidation(role.getId()); - getDelegateForUpdate(); - return updated.removeRole(role); - } - - @Override - public Set getRoles() { - if (updated != null) return updated.getRoles(); - - Set roles = new HashSet(); - for (String id : cached.getRoles().values()) { - RoleModel roleById = cacheSession.getRoleById(id, cachedRealm); - if (roleById == null) continue; - roles.add(roleById); - } - return roles; - } - - @Override - public int getNodeReRegistrationTimeout() { - if (updated != null) return updated.getNodeReRegistrationTimeout(); - return cached.getNodeReRegistrationTimeout(); - } - - @Override - public void setNodeReRegistrationTimeout(int timeout) { - getDelegateForUpdate(); - updated.setNodeReRegistrationTimeout(timeout); - } - - @Override - public Map getRegisteredNodes() { - if (updated != null) return updated.getRegisteredNodes(); - return cached.getRegisteredNodes(); - } - - @Override - public void registerNode(String nodeHost, int registrationTime) { - getDelegateForUpdate(); - updated.registerNode(nodeHost, registrationTime); - } - - @Override - public void unregisterNode(String nodeHost) { - getDelegateForUpdate(); - updated.unregisterNode(nodeHost); - } - - @Override - public boolean hasScope(RoleModel role) { - if (super.hasScope(role)) { - return true; - } - Set roles = getRoles(); - if (roles.contains(role)) return true; - - for (RoleModel mapping : roles) { - if (mapping.hasRole(role)) return true; - } - return false; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || !(o instanceof ApplicationModel)) return false; - - ApplicationModel that = (ApplicationModel) o; - return that.getId().equals(getId()); - } - - @Override - public int hashCode() { - return getId().hashCode(); - } - -} diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheRealmProvider.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheRealmProvider.java index 8a4c8691f1..9810d5022e 100755 --- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheRealmProvider.java +++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheRealmProvider.java @@ -17,8 +17,4 @@ public interface CacheRealmProvider extends RealmProvider { void registerApplicationInvalidation(String id); void registerRoleInvalidation(String id); - - void registerOAuthClientInvalidation(String id); - - void registerUserInvalidation(String id); } diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/ClientAdapter.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/ClientAdapter.java index 12e89e1ae4..5330fbc18a 100755 --- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/ClientAdapter.java +++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/ClientAdapter.java @@ -1,12 +1,12 @@ package org.keycloak.models.cache; -import org.keycloak.models.ClientIdentityProviderMappingModel; import org.keycloak.models.ClientModel; +import org.keycloak.models.ClientIdentityProviderMappingModel; 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.entities.CachedClient; +import org.keycloak.models.cache.entities.CachedApplication; import java.util.HashMap; import java.util.HashSet; @@ -18,80 +18,88 @@ import java.util.Set; * @author Bill Burke * @version $Revision: 1 $ */ -public abstract class ClientAdapter implements ClientModel { - protected CachedClient cachedClient; +public class ClientAdapter implements ClientModel { protected CacheRealmProvider cacheSession; - protected ClientModel updatedClient; protected RealmModel cachedRealm; protected RealmCache cache; - public ClientAdapter(RealmModel cachedRealm, CachedClient cached, RealmCache cache, CacheRealmProvider cacheSession) { + protected ClientModel updated; + protected CachedApplication cached; + + public ClientAdapter(RealmModel cachedRealm, CachedApplication cached, CacheRealmProvider cacheSession, RealmCache cache) { this.cachedRealm = cachedRealm; this.cache = cache; this.cacheSession = cacheSession; - this.cachedClient = cached; + this.cached = cached; } - protected abstract void getDelegateForUpdate(); + private void getDelegateForUpdate() { + if (updated == null) { + cacheSession.registerApplicationInvalidation(getId()); + updated = updated = cacheSession.getDelegate().getClientById(getId(), cachedRealm); + if (updated == null) throw new IllegalStateException("Not found in database"); + } + } + + @Override + public void updateClient() { + if (updated != null) updated.updateClient(); + } @Override public String getId() { - if (updatedClient != null) return updatedClient.getId(); - return cachedClient.getId(); + if (updated != null) return updated.getId(); + return cached.getId(); } - - @Override - public abstract String getClientId(); - public Set getWebOrigins() { - if (updatedClient != null) return updatedClient.getWebOrigins(); - return cachedClient.getWebOrigins(); + if (updated != null) return updated.getWebOrigins(); + return cached.getWebOrigins(); } public void setWebOrigins(Set webOrigins) { getDelegateForUpdate(); - updatedClient.setWebOrigins(webOrigins); + updated.setWebOrigins(webOrigins); } public void addWebOrigin(String webOrigin) { getDelegateForUpdate(); - updatedClient.addWebOrigin(webOrigin); + updated.addWebOrigin(webOrigin); } public void removeWebOrigin(String webOrigin) { getDelegateForUpdate(); - updatedClient.removeWebOrigin(webOrigin); + updated.removeWebOrigin(webOrigin); } public Set getRedirectUris() { - if (updatedClient != null) return updatedClient.getRedirectUris(); - return cachedClient.getRedirectUris(); + if (updated != null) return updated.getRedirectUris(); + return cached.getRedirectUris(); } public void setRedirectUris(Set redirectUris) { getDelegateForUpdate(); - updatedClient.setRedirectUris(redirectUris); + updated.setRedirectUris(redirectUris); } public void addRedirectUri(String redirectUri) { getDelegateForUpdate(); - updatedClient.addRedirectUri(redirectUri); + updated.addRedirectUri(redirectUri); } public void removeRedirectUri(String redirectUri) { getDelegateForUpdate(); - updatedClient.removeRedirectUri(redirectUri); + updated.removeRedirectUri(redirectUri); } public boolean isEnabled() { - if (updatedClient != null) return updatedClient.isEnabled(); - return cachedClient.isEnabled(); + if (updated != null) return updated.isEnabled(); + return cached.isEnabled(); } public void setEnabled(boolean enabled) { getDelegateForUpdate(); - updatedClient.setEnabled(enabled); + updated.setEnabled(enabled); } public boolean validateSecret(String secret) { @@ -99,62 +107,62 @@ public abstract class ClientAdapter implements ClientModel { } public String getSecret() { - if (updatedClient != null) return updatedClient.getSecret(); - return cachedClient.getSecret(); + if (updated != null) return updated.getSecret(); + return cached.getSecret(); } public void setSecret(String secret) { getDelegateForUpdate(); - updatedClient.setSecret(secret); + updated.setSecret(secret); } public boolean isPublicClient() { - if (updatedClient != null) return updatedClient.isPublicClient(); - return cachedClient.isPublicClient(); + if (updated != null) return updated.isPublicClient(); + return cached.isPublicClient(); } public void setPublicClient(boolean flag) { getDelegateForUpdate(); - updatedClient.setPublicClient(flag); + updated.setPublicClient(flag); } public boolean isFrontchannelLogout() { - if (updatedClient != null) return updatedClient.isPublicClient(); - return cachedClient.isFrontchannelLogout(); + if (updated != null) return updated.isPublicClient(); + return cached.isFrontchannelLogout(); } public void setFrontchannelLogout(boolean flag) { getDelegateForUpdate(); - updatedClient.setFrontchannelLogout(flag); + updated.setFrontchannelLogout(flag); } @Override public boolean isFullScopeAllowed() { - if (updatedClient != null) return updatedClient.isFullScopeAllowed(); - return cachedClient.isFullScopeAllowed(); + if (updated != null) return updated.isFullScopeAllowed(); + return cached.isFullScopeAllowed(); } @Override public void setFullScopeAllowed(boolean value) { getDelegateForUpdate(); - updatedClient.setFullScopeAllowed(value); + updated.setFullScopeAllowed(value); } public boolean isDirectGrantsOnly() { - if (updatedClient != null) return updatedClient.isDirectGrantsOnly(); - return cachedClient.isDirectGrantsOnly(); + if (updated != null) return updated.isDirectGrantsOnly(); + return cached.isDirectGrantsOnly(); } public void setDirectGrantsOnly(boolean flag) { getDelegateForUpdate(); - updatedClient.setDirectGrantsOnly(flag); + updated.setDirectGrantsOnly(flag); } public Set getScopeMappings() { - if (updatedClient != null) return updatedClient.getScopeMappings(); + if (updated != null) return updated.getScopeMappings(); Set roles = new HashSet(); - for (String id : cachedClient.getScope()) { + for (String id : cached.getScope()) { roles.add(cacheSession.getRoleById(id, getRealm())); } @@ -163,12 +171,12 @@ public abstract class ClientAdapter implements ClientModel { public void addScopeMapping(RoleModel role) { getDelegateForUpdate(); - updatedClient.addScopeMapping(role); + updated.addScopeMapping(role); } public void deleteScopeMapping(RoleModel role) { getDelegateForUpdate(); - updatedClient.deleteScopeMapping(role); + updated.deleteScopeMapping(role); } public Set getRealmScopeMappings() { @@ -187,119 +195,107 @@ public abstract class ClientAdapter implements ClientModel { return appRoles; } - public boolean hasScope(RoleModel role) { - if (updatedClient != null) return updatedClient.hasScope(role); - if (cachedClient.isFullScopeAllowed() || cachedClient.getScope().contains(role.getId())) return true; - - Set roles = getScopeMappings(); - - for (RoleModel mapping : roles) { - if (mapping.hasRole(role)) return true; - } - return false; - } - public RealmModel getRealm() { return cachedRealm; } public int getNotBefore() { - if (updatedClient != null) return updatedClient.getNotBefore(); - return cachedClient.getNotBefore(); + if (updated != null) return updated.getNotBefore(); + return cached.getNotBefore(); } public void setNotBefore(int notBefore) { getDelegateForUpdate(); - updatedClient.setNotBefore(notBefore); + updated.setNotBefore(notBefore); } @Override public String getProtocol() { - if (updatedClient != null) return updatedClient.getProtocol(); - return cachedClient.getProtocol(); + if (updated != null) return updated.getProtocol(); + return cached.getProtocol(); } @Override public void setProtocol(String protocol) { getDelegateForUpdate(); - updatedClient.setProtocol(protocol); + updated.setProtocol(protocol); } @Override public void setAttribute(String name, String value) { getDelegateForUpdate(); - updatedClient.setAttribute(name, value); + updated.setAttribute(name, value); } @Override public void removeAttribute(String name) { getDelegateForUpdate(); - updatedClient.removeAttribute(name); + updated.removeAttribute(name); } @Override public String getAttribute(String name) { - if (updatedClient != null) return updatedClient.getAttribute(name); - return cachedClient.getAttributes().get(name); + if (updated != null) return updated.getAttribute(name); + return cached.getAttributes().get(name); } @Override public Map getAttributes() { - if (updatedClient != null) return updatedClient.getAttributes(); + if (updated != null) return updated.getAttributes(); Map copy = new HashMap(); - copy.putAll(cachedClient.getAttributes()); + copy.putAll(cached.getAttributes()); return copy; } @Override public void updateIdentityProviders(List identityProviders) { getDelegateForUpdate(); - updatedClient.updateIdentityProviders(identityProviders); + updated.updateIdentityProviders(identityProviders); } @Override public List getIdentityProviders() { - if (updatedClient != null) return updatedClient.getIdentityProviders(); - return cachedClient.getIdentityProviders(); + if (updated != null) return updated.getIdentityProviders(); + return cached.getIdentityProviders(); } @Override public boolean isAllowedRetrieveTokenFromIdentityProvider(String providerId) { - if (updatedClient != null) return updatedClient.isAllowedRetrieveTokenFromIdentityProvider(providerId); - return cachedClient.isAllowedRetrieveTokenFromIdentityProvider(providerId); + if (updated != null) return updated.isAllowedRetrieveTokenFromIdentityProvider(providerId); + return cached.isAllowedRetrieveTokenFromIdentityProvider(providerId); } @Override public Set getProtocolMappers() { - if (updatedClient != null) return updatedClient.getProtocolMappers(); - return cachedClient.getProtocolMappers(); + if (updated != null) return updated.getProtocolMappers(); + return cached.getProtocolMappers(); } @Override public ProtocolMapperModel addProtocolMapper(ProtocolMapperModel model) { getDelegateForUpdate(); - return updatedClient.addProtocolMapper(model); + return updated.addProtocolMapper(model); } @Override public void removeProtocolMapper(ProtocolMapperModel mapping) { getDelegateForUpdate(); - updatedClient.removeProtocolMapper(mapping); + updated.removeProtocolMapper(mapping); } @Override public void updateProtocolMapper(ProtocolMapperModel mapping) { getDelegateForUpdate(); - updatedClient.updateProtocolMapper(mapping); + updated.updateProtocolMapper(mapping); } @Override public ProtocolMapperModel getProtocolMapperById(String id) { - for (ProtocolMapperModel mapping : cachedClient.getProtocolMappers()) { + for (ProtocolMapperModel mapping : cached.getProtocolMappers()) { if (mapping.getId().equals(id)) return mapping; } return null; @@ -307,9 +303,228 @@ public abstract class ClientAdapter implements ClientModel { @Override public ProtocolMapperModel getProtocolMapperByName(String protocol, String name) { - for (ProtocolMapperModel mapping : cachedClient.getProtocolMappers()) { + for (ProtocolMapperModel mapping : cached.getProtocolMappers()) { if (mapping.getProtocol().equals(protocol) && mapping.getName().equals(name)) return mapping; } return null; } + + @Override + public String getClientId() { + if (updated != null) return updated.getClientId(); + return cached.getName(); + } + + @Override + public void setClientId(String clientId) { + getDelegateForUpdate(); + updated.setClientId(clientId); + cacheSession.registerRealmInvalidation(cachedRealm.getId()); + } + + @Override + public boolean isSurrogateAuthRequired() { + if (updated != null) return updated.isSurrogateAuthRequired(); + return cached.isSurrogateAuthRequired(); + } + + @Override + public void setSurrogateAuthRequired(boolean surrogateAuthRequired) { + getDelegateForUpdate(); + updated.setSurrogateAuthRequired(surrogateAuthRequired); + } + + @Override + public String getManagementUrl() { + if (updated != null) return updated.getManagementUrl(); + return cached.getManagementUrl(); + } + + @Override + public void setManagementUrl(String url) { + getDelegateForUpdate(); + updated.setManagementUrl(url); + } + + @Override + public String getBaseUrl() { + if (updated != null) return updated.getBaseUrl(); + return cached.getBaseUrl(); + } + + @Override + public void setBaseUrl(String url) { + getDelegateForUpdate(); + updated.setBaseUrl(url); + } + + @Override + public List getDefaultRoles() { + if (updated != null) return updated.getDefaultRoles(); + return cached.getDefaultRoles(); + } + + @Override + public void addDefaultRole(String name) { + getDelegateForUpdate(); + updated.addDefaultRole(name); + } + + @Override + public void updateDefaultRoles(String[] defaultRoles) { + getDelegateForUpdate(); + updated.updateDefaultRoles(defaultRoles); + } + + @Override + public Set getClientScopeMappings(ClientModel client) { + Set roleMappings = client.getScopeMappings(); + + Set appRoles = new HashSet(); + for (RoleModel role : roleMappings) { + RoleContainerModel container = role.getContainer(); + if (container instanceof RealmModel) { + } else { + ClientModel app = (ClientModel)container; + if (app.getId().equals(getId())) { + appRoles.add(role); + } + } + } + + return appRoles; + } + + @Override + public boolean isBearerOnly() { + if (updated != null) return updated.isBearerOnly(); + return cached.isBearerOnly(); + } + + @Override + public void setBearerOnly(boolean only) { + getDelegateForUpdate(); + updated.setBearerOnly(only); + } + + @Override + public boolean isConsentRequired() { + if (updated != null) return updated.isConsentRequired(); + return cached.isConsentRequired(); + } + + @Override + public void setConsentRequired(boolean consentRequired) { + getDelegateForUpdate(); + updated.setConsentRequired(consentRequired); + } + + @Override + public RoleModel getRole(String name) { + if (updated != null) return updated.getRole(name); + String id = cached.getRoles().get(name); + if (id == null) return null; + return cacheSession.getRoleById(id, cachedRealm); + } + + @Override + public RoleModel addRole(String name) { + getDelegateForUpdate(); + RoleModel role = updated.addRole(name); + cacheSession.registerRoleInvalidation(role.getId()); + return role; + } + + @Override + public RoleModel addRole(String id, String name) { + getDelegateForUpdate(); + RoleModel role = updated.addRole(id, name); + cacheSession.registerRoleInvalidation(role.getId()); + return role; + } + + @Override + public boolean removeRole(RoleModel role) { + cacheSession.registerRoleInvalidation(role.getId()); + getDelegateForUpdate(); + return updated.removeRole(role); + } + + @Override + public Set getRoles() { + if (updated != null) return updated.getRoles(); + + Set roles = new HashSet(); + for (String id : cached.getRoles().values()) { + RoleModel roleById = cacheSession.getRoleById(id, cachedRealm); + if (roleById == null) continue; + roles.add(roleById); + } + return roles; + } + + @Override + public int getNodeReRegistrationTimeout() { + if (updated != null) return updated.getNodeReRegistrationTimeout(); + return cached.getNodeReRegistrationTimeout(); + } + + @Override + public void setNodeReRegistrationTimeout(int timeout) { + getDelegateForUpdate(); + updated.setNodeReRegistrationTimeout(timeout); + } + + @Override + public Map getRegisteredNodes() { + if (updated != null) return updated.getRegisteredNodes(); + return cached.getRegisteredNodes(); + } + + @Override + public void registerNode(String nodeHost, int registrationTime) { + getDelegateForUpdate(); + updated.registerNode(nodeHost, registrationTime); + } + + @Override + public void unregisterNode(String nodeHost) { + getDelegateForUpdate(); + updated.unregisterNode(nodeHost); + } + + @Override + public boolean hasScope(RoleModel role) { + if (updated != null) return updated.hasScope(role); + if (cached.isFullScopeAllowed() || cached.getScope().contains(role.getId())) return true; + + Set roles = getScopeMappings(); + + for (RoleModel mapping : roles) { + if (mapping.hasRole(role)) return true; + } + + roles = getRoles(); + if (roles.contains(role)) return true; + + for (RoleModel mapping : roles) { + if (mapping.hasRole(role)) return true; + } + return false; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || !(o instanceof ClientModel)) return false; + + ClientModel that = (ClientModel) o; + return that.getId().equals(getId()); + } + + @Override + public int hashCode() { + return getId().hashCode(); + } + } diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/DefaultCacheRealmProvider.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/DefaultCacheRealmProvider.java index a1d232ecb3..933ac743b0 100755 --- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/DefaultCacheRealmProvider.java +++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/DefaultCacheRealmProvider.java @@ -1,15 +1,13 @@ package org.keycloak.models.cache; -import org.keycloak.models.ApplicationModel; +import org.keycloak.models.ClientModel; import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakTransaction; -import org.keycloak.models.OAuthClientModel; import org.keycloak.models.RealmModel; import org.keycloak.models.RealmProvider; import org.keycloak.models.RoleModel; import org.keycloak.models.cache.entities.CachedApplication; import org.keycloak.models.cache.entities.CachedApplicationRole; -import org.keycloak.models.cache.entities.CachedOAuthClient; import org.keycloak.models.cache.entities.CachedRealm; import org.keycloak.models.cache.entities.CachedRealmRole; import org.keycloak.models.cache.entities.CachedRole; @@ -34,11 +32,8 @@ public class DefaultCacheRealmProvider implements CacheRealmProvider { protected Set realmInvalidations = new HashSet(); protected Set appInvalidations = new HashSet(); protected Set roleInvalidations = new HashSet(); - protected Set clientInvalidations = new HashSet(); - protected Set userInvalidations = new HashSet(); protected Map managedRealms = new HashMap(); - protected Map managedApplications = new HashMap(); - protected Map managedClients = new HashMap(); + protected Map managedApplications = new HashMap(); protected Map managedRoles = new HashMap(); protected boolean clearAll; @@ -83,16 +78,6 @@ public class DefaultCacheRealmProvider implements CacheRealmProvider { roleInvalidations.add(id); } - @Override - public void registerOAuthClientInvalidation(String id) { - clientInvalidations.add(id); - } - - @Override - public void registerUserInvalidation(String id) { - userInvalidations.add(id); - } - protected void runInvalidations() { for (String id : realmInvalidations) { cache.invalidateCachedRealmById(id); @@ -103,9 +88,6 @@ public class DefaultCacheRealmProvider implements CacheRealmProvider { for (String id : appInvalidations) { cache.invalidateCachedApplicationById(id); } - for (String id : clientInvalidations) { - cache.invalidateCachedOAuthClientById(id); - } } private KeycloakTransaction getTransaction() { @@ -252,8 +234,8 @@ public class DefaultCacheRealmProvider implements CacheRealmProvider { RoleModel model = getDelegate().getRoleById(id, realm); if (model == null) return null; if (roleInvalidations.contains(id)) return model; - if (model.getContainer() instanceof ApplicationModel) { - cached = new CachedApplicationRole(((ApplicationModel) model.getContainer()).getId(), model, realm); + if (model.getContainer() instanceof ClientModel) { + cached = new CachedApplicationRole(((ClientModel) model.getContainer()).getId(), model, realm); } else { cached = new CachedRealmRole(model, realm); } @@ -270,51 +252,27 @@ public class DefaultCacheRealmProvider implements CacheRealmProvider { } @Override - public ApplicationModel getApplicationById(String id, RealmModel realm) { - if (!cache.isEnabled()) return getDelegate().getApplicationById(id, realm); + public ClientModel getClientById(String id, RealmModel realm) { + if (!cache.isEnabled()) return getDelegate().getClientById(id, realm); CachedApplication cached = cache.getApplication(id); if (cached != null && !cached.getRealm().equals(realm.getId())) { cached = null; } if (cached == null) { - ApplicationModel model = getDelegate().getApplicationById(id, realm); + ClientModel model = getDelegate().getClientById(id, realm); if (model == null) return null; if (appInvalidations.contains(id)) return model; cached = new CachedApplication(cache, getDelegate(), realm, model); cache.addCachedApplication(cached); } else if (appInvalidations.contains(id)) { - return getDelegate().getApplicationById(id, realm); + return getDelegate().getClientById(id, realm); } else if (managedApplications.containsKey(id)) { return managedApplications.get(id); } - ApplicationAdapter adapter = new ApplicationAdapter(realm, cached, this, cache); + ClientAdapter adapter = new ClientAdapter(realm, cached, this, cache); managedApplications.put(id, adapter); return adapter; } - @Override - public OAuthClientModel getOAuthClientById(String id, RealmModel realm) { - if (!cache.isEnabled()) return getDelegate().getOAuthClientById(id, realm); - CachedOAuthClient cached = cache.getOAuthClient(id); - if (cached != null && !cached.getRealm().equals(realm.getId())) { - cached = null; - } - - if (cached == null) { - OAuthClientModel model = getDelegate().getOAuthClientById(id, realm); - if (model == null) return null; - if (clientInvalidations.contains(id)) return model; - cached = new CachedOAuthClient(cache, getDelegate(), realm, model); - cache.addCachedOAuthClient(cached); - } else if (clientInvalidations.contains(id)) { - return getDelegate().getOAuthClientById(id, realm); - } else if (managedClients.containsKey(id)) { - return managedClients.get(id); - } - OAuthClientAdapter adapter = new OAuthClientAdapter(realm, cached, this, cache); - managedClients.put(id, adapter); - return adapter; - } - } diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/MemoryRealmCache.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/MemoryRealmCache.java index 2373f9f8a7..25064c6764 100755 --- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/MemoryRealmCache.java +++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/MemoryRealmCache.java @@ -1,7 +1,6 @@ package org.keycloak.models.cache; import org.keycloak.models.cache.entities.CachedApplication; -import org.keycloak.models.cache.entities.CachedOAuthClient; import org.keycloak.models.cache.entities.CachedRealm; import org.keycloak.models.cache.entities.CachedRole; @@ -16,7 +15,6 @@ public class MemoryRealmCache implements RealmCache { protected ConcurrentHashMap realmCache = new ConcurrentHashMap(); protected ConcurrentHashMap realmCacheByName = new ConcurrentHashMap(); protected ConcurrentHashMap applicationCache = new ConcurrentHashMap(); - protected ConcurrentHashMap clientCache = new ConcurrentHashMap(); protected ConcurrentHashMap roleCache = new ConcurrentHashMap(); protected volatile boolean enabled = true; @@ -25,7 +23,6 @@ public class MemoryRealmCache implements RealmCache { realmCache.clear(); realmCacheByName.clear(); applicationCache.clear(); - clientCache.clear(); roleCache.clear(); } @@ -96,28 +93,6 @@ public class MemoryRealmCache implements RealmCache { applicationCache.remove(id); } - @Override - public CachedOAuthClient getOAuthClient(String id) { - if (!enabled) return null; - return clientCache.get(id); - } - - @Override - public void invalidateOAuthClient(CachedOAuthClient client) { - clientCache.remove(client.getId()); - } - - @Override - public void addCachedOAuthClient(CachedOAuthClient client) { - if (!enabled) return; - clientCache.put(client.getId(), client); - } - - @Override - public void invalidateCachedOAuthClientById(String id) { - clientCache.remove(id); - } - @Override public CachedRole getRole(String id) { if (!enabled) return null; diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/NoCacheRealmProvider.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/NoCacheRealmProvider.java index e7b1551c2d..12c28f637b 100755 --- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/NoCacheRealmProvider.java +++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/NoCacheRealmProvider.java @@ -1,8 +1,7 @@ package org.keycloak.models.cache; -import org.keycloak.models.ApplicationModel; +import org.keycloak.models.ClientModel; import org.keycloak.models.KeycloakSession; -import org.keycloak.models.OAuthClientModel; import org.keycloak.models.RealmModel; import org.keycloak.models.RealmProvider; import org.keycloak.models.RoleModel; @@ -50,10 +49,6 @@ public class NoCacheRealmProvider implements CacheRealmProvider { public void registerRoleInvalidation(String id) { } - @Override - public void registerOAuthClientInvalidation(String id) { - } - @Override public RealmModel createRealm(String name) { return getDelegate().createRealm(name); @@ -96,17 +91,7 @@ public class NoCacheRealmProvider implements CacheRealmProvider { } @Override - public ApplicationModel getApplicationById(String id, RealmModel realm) { - return getDelegate().getApplicationById(id, realm); - } - - @Override - public OAuthClientModel getOAuthClientById(String id, RealmModel realm) { - return getDelegate().getOAuthClientById(id, realm); - } - - @Override - public void registerUserInvalidation(String id) { - //To change body of implemented methods use File | Settings | File Templates. + public ClientModel getClientById(String id, RealmModel realm) { + return getDelegate().getClientById(id, realm); } } diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/OAuthClientAdapter.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/OAuthClientAdapter.java deleted file mode 100755 index 1fe5b25e5d..0000000000 --- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/OAuthClientAdapter.java +++ /dev/null @@ -1,56 +0,0 @@ -package org.keycloak.models.cache; - -import org.keycloak.models.OAuthClientModel; -import org.keycloak.models.RealmModel; -import org.keycloak.models.cache.entities.CachedOAuthClient; - -/** - * @author Bill Burke - * @version $Revision: 1 $ - */ -public class OAuthClientAdapter extends ClientAdapter implements OAuthClientModel { - protected OAuthClientModel updated; - protected CachedOAuthClient cached; - - public OAuthClientAdapter(RealmModel cachedRealm, CachedOAuthClient cached, CacheRealmProvider cacheSession, RealmCache cache) { - super(cachedRealm, cached, cache, cacheSession); - this.cached = cached; - } - - @Override - protected void getDelegateForUpdate() { - if (updated == null) { - cacheSession.registerOAuthClientInvalidation(getId()); - updatedClient = updated = cacheSession.getDelegate().getOAuthClientById(getId(), cachedRealm); - if (updated == null) throw new IllegalStateException("Not found in database"); - } - } - - @Override - public String getClientId() { - if (updated != null) return updated.getClientId(); - return cached.getName(); - } - - @Override - public void setClientId(String id) { - getDelegateForUpdate(); - updated.setClientId(id); - cacheSession.registerRealmInvalidation(cachedRealm.getId()); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || !(o instanceof OAuthClientModel)) return false; - - OAuthClientModel that = (OAuthClientModel) o; - - return that.getId().equals(this.getId()); - } - - @Override - public int hashCode() { - return getId().hashCode(); - } -} diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmAdapter.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmAdapter.java index ef18caa6df..f2532af4b3 100755 --- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmAdapter.java +++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmAdapter.java @@ -2,20 +2,15 @@ package org.keycloak.models.cache; import org.keycloak.Config; import org.keycloak.enums.SslRequired; -import org.keycloak.models.ApplicationModel; -import org.keycloak.models.ClaimTypeModel; import org.keycloak.models.ClientModel; import org.keycloak.models.IdentityProviderMapperModel; import org.keycloak.models.IdentityProviderModel; -import org.keycloak.models.OAuthClientModel; import org.keycloak.models.PasswordPolicy; -import org.keycloak.models.ProtocolMapperModel; import org.keycloak.models.RealmModel; import org.keycloak.models.RequiredCredentialModel; import org.keycloak.models.RoleModel; import org.keycloak.models.UserFederationProviderModel; import org.keycloak.models.cache.entities.CachedRealm; -import org.keycloak.models.entities.IdentityProviderMapperEntity; import org.keycloak.models.utils.KeycloakModelUtils; import java.security.Key; @@ -476,39 +471,25 @@ public class RealmAdapter implements RealmModel { } @Override - public ClientModel findClient(String clientId) { - if (updated != null) return updated.findClient(clientId); - String appId = cached.getApplications().get(clientId); - if (appId != null) { - return cacheSession.getApplicationById(appId, this); - } - String oauth = cached.getClients().get(clientId); - if (oauth != null) { - return cacheSession.getOAuthClientById(oauth, this); - } - return null; - } - - @Override - public Map getApplicationNameMap() { - if (updated != null) return updated.getApplicationNameMap(); - Map map = new HashMap(); + public Map getClientNameMap() { + if (updated != null) return updated.getClientNameMap(); + Map map = new HashMap(); for (String id : cached.getApplications().values()) { - ApplicationModel model = cacheSession.getApplicationById(id, this); + ClientModel model = cacheSession.getClientById(id, this); if (model == null) { throw new IllegalStateException("Cached application not found: " + id); } - map.put(model.getName(), model); + map.put(model.getClientId(), model); } return map; } @Override - public List getApplications() { - if (updated != null) return updated.getApplications(); - List apps = new LinkedList(); + public List getClients() { + if (updated != null) return updated.getClients(); + List apps = new LinkedList(); for (String id : cached.getApplications().values()) { - ApplicationModel model = cacheSession.getApplicationById(id, this); + ClientModel model = cacheSession.getClientById(id, this); if (model == null) { throw new IllegalStateException("Cached application not found: " + id); } @@ -519,40 +500,40 @@ public class RealmAdapter implements RealmModel { } @Override - public ApplicationModel addApplication(String name) { + public ClientModel addClient(String name) { getDelegateForUpdate(); - ApplicationModel app = updated.addApplication(name); + ClientModel app = updated.addClient(name); cacheSession.registerApplicationInvalidation(app.getId()); return app; } @Override - public ApplicationModel addApplication(String id, String name) { + public ClientModel addClient(String id, String clientId) { getDelegateForUpdate(); - ApplicationModel app = updated.addApplication(id, name); + ClientModel app = updated.addClient(id, clientId); cacheSession.registerApplicationInvalidation(app.getId()); return app; } @Override - public boolean removeApplication(String id) { + public boolean removeClient(String id) { cacheSession.registerApplicationInvalidation(id); getDelegateForUpdate(); - return updated.removeApplication(id); + return updated.removeClient(id); } @Override - public ApplicationModel getApplicationById(String id) { - if (updated != null) return updated.getApplicationById(id); - return cacheSession.getApplicationById(id, this); + public ClientModel getClientById(String id) { + if (updated != null) return updated.getClientById(id); + return cacheSession.getClientById(id, this); } @Override - public ApplicationModel getApplicationByName(String name) { - if (updated != null) return updated.getApplicationByName(name); - String id = cached.getApplications().get(name); + public ClientModel getClientByClientId(String clientId) { + if (updated != null) return updated.getClientByClientId(clientId); + String id = cached.getApplications().get(clientId); if (id == null) return null; - return getApplicationById(id); + return getClientById(id); } @Override @@ -561,57 +542,6 @@ public class RealmAdapter implements RealmModel { updated.updateRequiredCredentials(creds); } - @Override - public OAuthClientModel addOAuthClient(String name) { - getDelegateForUpdate(); - OAuthClientModel client = updated.addOAuthClient(name); - cacheSession.registerOAuthClientInvalidation(client.getId()); - return client; - } - - @Override - public OAuthClientModel addOAuthClient(String id, String name) { - getDelegateForUpdate(); - OAuthClientModel client = updated.addOAuthClient(id, name); - cacheSession.registerOAuthClientInvalidation(client.getId()); - return client; - } - - @Override - public OAuthClientModel getOAuthClient(String name) { - if (updated != null) return updated.getOAuthClient(name); - String id = cached.getClients().get(name); - if (id == null) return null; - return getOAuthClientById(id); - } - - @Override - public OAuthClientModel getOAuthClientById(String id) { - if (updated != null) return updated.getOAuthClientById(id); - return cacheSession.getOAuthClientById(id, this); - } - - @Override - public boolean removeOAuthClient(String id) { - cacheSession.registerOAuthClientInvalidation(id); - getDelegateForUpdate(); - return updated.removeOAuthClient(id); - } - - @Override - public List getOAuthClients() { - if (updated != null) return updated.getOAuthClients(); - List clients = new LinkedList(); - for (String id : cached.getClients().values()) { - OAuthClientModel model = cacheSession.getOAuthClientById(id, this); - if (model == null) { - throw new IllegalStateException("Cached oauth client not found: " + id); - } - clients.add(model); - } - return clients; - } - @Override public Map getBrowserSecurityHeaders() { if (updated != null) return updated.getBrowserSecurityHeaders(); @@ -821,14 +751,14 @@ public class RealmAdapter implements RealmModel { } @Override - public ApplicationModel getMasterAdminApp() { - return cacheSession.getRealm(Config.getAdminRealm()).getApplicationById(cached.getMasterAdminApp()); + public ClientModel getMasterAdminClient() { + return cacheSession.getRealm(Config.getAdminRealm()).getClientById(cached.getMasterAdminApp()); } @Override - public void setMasterAdminApp(ApplicationModel app) { + public void setMasterAdminClient(ClientModel client) { getDelegateForUpdate(); - updated.setMasterAdminApp(app); + updated.setMasterAdminClient(client); } @Override @@ -875,13 +805,6 @@ public class RealmAdapter implements RealmModel { return roles; } - @Override - public ClientModel findClientById(String id) { - ClientModel model = getApplicationById(id); - if (model != null) return model; - return getOAuthClientById(id); - } - @Override public boolean isIdentityFederationEnabled() { if (updated != null) return updated.isIdentityFederationEnabled(); diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmCache.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmCache.java index 246a6ea94d..3d6646200f 100755 --- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmCache.java +++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmCache.java @@ -1,7 +1,6 @@ package org.keycloak.models.cache; import org.keycloak.models.cache.entities.CachedApplication; -import org.keycloak.models.cache.entities.CachedOAuthClient; import org.keycloak.models.cache.entities.CachedRealm; import org.keycloak.models.cache.entities.CachedRole; @@ -30,14 +29,6 @@ public interface RealmCache { void invalidateCachedApplicationById(String id); - CachedOAuthClient getOAuthClient(String id); - - void invalidateOAuthClient(CachedOAuthClient client); - - void addCachedOAuthClient(CachedOAuthClient client); - - void invalidateCachedOAuthClientById(String id); - CachedRole getRole(String id); void invalidateRole(CachedRole role); @@ -46,7 +37,6 @@ public interface RealmCache { void invalidateCachedRoleById(String id); - void invalidateRoleById(String id); boolean isEnabled(); diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RoleAdapter.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RoleAdapter.java index 18f642241f..0f30ecdd2a 100755 --- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RoleAdapter.java +++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RoleAdapter.java @@ -107,7 +107,7 @@ public class RoleAdapter implements RoleModel { return realm; } else { CachedApplicationRole appRole = (CachedApplicationRole)cached; - return realm.getApplicationById(appRole.getAppId()); + return realm.getClientById(appRole.getAppId()); } } diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/UserAdapter.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/UserAdapter.java index 14aea05e47..2087fc20ea 100755 --- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/UserAdapter.java +++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/UserAdapter.java @@ -1,6 +1,6 @@ package org.keycloak.models.cache; -import org.keycloak.models.ApplicationModel; +import org.keycloak.models.ClientModel; import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; import org.keycloak.models.RoleContainerModel; @@ -219,14 +219,14 @@ public class UserAdapter implements UserModel { } @Override - public Set getApplicationRoleMappings(ApplicationModel app) { - if (updated != null) return updated.getApplicationRoleMappings(app); + public Set getClientRoleMappings(ClientModel app) { + if (updated != null) return updated.getClientRoleMappings(app); Set roleMappings = getRoleMappings(); Set appMappings = new HashSet(); for (RoleModel role : roleMappings) { RoleContainerModel container = role.getContainer(); - if (container instanceof ApplicationModel) { - if (((ApplicationModel) container).getId().equals(app.getId())) { + if (container instanceof ClientModel) { + if (((ClientModel) container).getId().equals(app.getId())) { appMappings.add(role); } } diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedApplication.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedApplication.java index e537ea7483..896dfc96f3 100755 --- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedApplication.java +++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedApplication.java @@ -1,38 +1,82 @@ package org.keycloak.models.cache.entities; -import org.keycloak.models.ApplicationModel; +import org.keycloak.models.ClientModel; +import org.keycloak.models.ClientIdentityProviderMappingModel; +import org.keycloak.models.ProtocolMapperModel; import org.keycloak.models.RealmModel; import org.keycloak.models.RealmProvider; import org.keycloak.models.RoleModel; import org.keycloak.models.cache.RealmCache; +import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.TreeMap; /** * @author Bill Burke * @version $Revision: 1 $ */ -public class CachedApplication extends CachedClient { +public class CachedApplication { + private String id; + private String name; + private String realm; + private Set redirectUris = new HashSet(); + private boolean enabled; + private String secret; + private String protocol; + private Map attributes = new HashMap(); + private boolean publicClient; + private boolean fullScopeAllowed; + private boolean directGrantsOnly; + private boolean frontchannelLogout; + private int notBefore; + private Set scope = new HashSet(); + private Set webOrigins = new HashSet(); + private List identityProviders = new ArrayList(); + private Set protocolMappers = new HashSet(); private boolean surrogateAuthRequired; private String managementUrl; private String baseUrl; private List defaultRoles = new LinkedList(); private boolean bearerOnly; + private boolean consentRequired; private Map roles = new HashMap(); private int nodeReRegistrationTimeout; private Map registeredNodes; - public CachedApplication(RealmCache cache, RealmProvider delegate, RealmModel realm, ApplicationModel model) { - super(cache, delegate, realm, model); + public CachedApplication(RealmCache cache, RealmProvider delegate, RealmModel realm, ClientModel model) { + id = model.getId(); + secret = model.getSecret(); + name = model.getClientId(); + this.realm = realm.getId(); + enabled = model.isEnabled(); + protocol = model.getProtocol(); + attributes.putAll(model.getAttributes()); + notBefore = model.getNotBefore(); + directGrantsOnly = model.isDirectGrantsOnly(); + frontchannelLogout = model.isFrontchannelLogout(); + publicClient = model.isPublicClient(); + fullScopeAllowed = model.isFullScopeAllowed(); + redirectUris.addAll(model.getRedirectUris()); + webOrigins.addAll(model.getWebOrigins()); + for (RoleModel role : model.getScopeMappings()) { + scope.add(role.getId()); + } + this.identityProviders = model.getIdentityProviders(); + for (ProtocolMapperModel mapper : model.getProtocolMappers()) { + this.protocolMappers.add(mapper); + } surrogateAuthRequired = model.isSurrogateAuthRequired(); managementUrl = model.getManagementUrl(); baseUrl = model.getBaseUrl(); defaultRoles.addAll(model.getDefaultRoles()); bearerOnly = model.isBearerOnly(); + consentRequired = model.isConsentRequired(); for (RoleModel role : model.getRoles()) { roles.put(role.getName(), role.getId()); cache.addCachedRole(new CachedApplicationRole(id, role, realm)); @@ -41,6 +85,93 @@ public class CachedApplication extends CachedClient { nodeReRegistrationTimeout = model.getNodeReRegistrationTimeout(); registeredNodes = new TreeMap(model.getRegisteredNodes()); } + public String getId() { + return id; + } + + public String getName() { + return name; + } + + public String getRealm() { + return realm; + } + + public Set getRedirectUris() { + return redirectUris; + } + + public boolean isEnabled() { + return enabled; + } + + public String getSecret() { + return secret; + } + + public boolean isPublicClient() { + return publicClient; + } + + public boolean isDirectGrantsOnly() { + return directGrantsOnly; + } + + public int getNotBefore() { + return notBefore; + } + + public Set getScope() { + return scope; + } + + public Set getWebOrigins() { + return webOrigins; + } + + public boolean isFullScopeAllowed() { + return fullScopeAllowed; + } + + public String getProtocol() { + return protocol; + } + + public Map getAttributes() { + return attributes; + } + + public boolean isFrontchannelLogout() { + return frontchannelLogout; + } + + public List getIdentityProviders() { + return this.identityProviders; + } + + public boolean hasIdentityProvider(String providerId) { + for (ClientIdentityProviderMappingModel model : getIdentityProviders()) { + if (model.getIdentityProvider().equals(providerId)) { + return true; + } + } + + return false; + } + + public Set getProtocolMappers() { + return protocolMappers; + } + + public boolean isAllowedRetrieveTokenFromIdentityProvider(String providerId) { + for (ClientIdentityProviderMappingModel model : getIdentityProviders()) { + if (model.getIdentityProvider().equals(providerId)) { + return model.isRetrieveToken(); + } + } + + return false; + } public boolean isSurrogateAuthRequired() { return surrogateAuthRequired; @@ -62,6 +193,10 @@ public class CachedApplication extends CachedClient { return bearerOnly; } + public boolean isConsentRequired() { + return consentRequired; + } + public Map getRoles() { return roles; } diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedClient.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedClient.java deleted file mode 100755 index f1f5ef151b..0000000000 --- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedClient.java +++ /dev/null @@ -1,152 +0,0 @@ -package org.keycloak.models.cache.entities; - -import org.keycloak.models.ClientIdentityProviderMappingModel; -import org.keycloak.models.ClientModel; -import org.keycloak.models.ProtocolMapperModel; -import org.keycloak.models.RealmModel; -import org.keycloak.models.RealmProvider; -import org.keycloak.models.RoleModel; -import org.keycloak.models.cache.RealmCache; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * @author Bill Burke - * @version $Revision: 1 $ - */ -public class CachedClient { - protected String id; - protected String name; - protected String realm; - protected Set redirectUris = new HashSet(); - protected boolean enabled; - protected String secret; - protected String protocol; - protected Map attributes = new HashMap(); - protected boolean publicClient; - protected boolean fullScopeAllowed; - protected boolean directGrantsOnly; - protected boolean frontchannelLogout; - protected int notBefore; - protected Set scope = new HashSet(); - protected Set webOrigins = new HashSet(); - private List identityProviders = new ArrayList(); - private Set protocolMappers = new HashSet(); - - public CachedClient(RealmCache cache, RealmProvider delegate, RealmModel realm, ClientModel model) { - id = model.getId(); - secret = model.getSecret(); - name = model.getClientId(); - this.realm = realm.getId(); - enabled = model.isEnabled(); - protocol = model.getProtocol(); - attributes.putAll(model.getAttributes()); - notBefore = model.getNotBefore(); - directGrantsOnly = model.isDirectGrantsOnly(); - frontchannelLogout = model.isFrontchannelLogout(); - publicClient = model.isPublicClient(); - fullScopeAllowed = model.isFullScopeAllowed(); - redirectUris.addAll(model.getRedirectUris()); - webOrigins.addAll(model.getWebOrigins()); - for (RoleModel role : model.getScopeMappings()) { - scope.add(role.getId()); - } - this.identityProviders = model.getIdentityProviders(); - for (ProtocolMapperModel mapper : model.getProtocolMappers()) { - this.protocolMappers.add(mapper); - } - } - - public String getId() { - return id; - } - - public String getName() { - return name; - } - - public String getRealm() { - return realm; - } - - public Set getRedirectUris() { - return redirectUris; - } - - public boolean isEnabled() { - return enabled; - } - - public String getSecret() { - return secret; - } - - public boolean isPublicClient() { - return publicClient; - } - - public boolean isDirectGrantsOnly() { - return directGrantsOnly; - } - - public int getNotBefore() { - return notBefore; - } - - public Set getScope() { - return scope; - } - - public Set getWebOrigins() { - return webOrigins; - } - - public boolean isFullScopeAllowed() { - return fullScopeAllowed; - } - - public String getProtocol() { - return protocol; - } - - public Map getAttributes() { - return attributes; - } - - public boolean isFrontchannelLogout() { - return frontchannelLogout; - } - - public List getIdentityProviders() { - return this.identityProviders; - } - - public boolean hasIdentityProvider(String providerId) { - for (ClientIdentityProviderMappingModel model : getIdentityProviders()) { - if (model.getIdentityProvider().equals(providerId)) { - return true; - } - } - - return false; - } - - public Set getProtocolMappers() { - return protocolMappers; - } - - public boolean isAllowedRetrieveTokenFromIdentityProvider(String providerId) { - for (ClientIdentityProviderMappingModel model : getIdentityProviders()) { - if (model.getIdentityProvider().equals(providerId)) { - return model.isRetrieveToken(); - } - } - - return false; - } -} diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedOAuthClient.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedOAuthClient.java deleted file mode 100755 index dfaceb9c82..0000000000 --- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedOAuthClient.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.keycloak.models.cache.entities; - -import org.keycloak.models.OAuthClientModel; -import org.keycloak.models.RealmModel; -import org.keycloak.models.RealmProvider; -import org.keycloak.models.cache.RealmCache; - -/** - * @author Bill Burke - * @version $Revision: 1 $ - */ -public class CachedOAuthClient extends CachedClient { - public CachedOAuthClient(RealmCache cache, RealmProvider delegate, RealmModel realm, OAuthClientModel model) { - super(cache, delegate, realm, model); - - } -} diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedRealm.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedRealm.java index a88cf47f3f..d302c48979 100755 --- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedRealm.java +++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedRealm.java @@ -1,392 +1,385 @@ -package org.keycloak.models.cache.entities; - -import org.keycloak.enums.SslRequired; -import org.keycloak.models.ApplicationModel; -import org.keycloak.models.IdentityProviderMapperModel; -import org.keycloak.models.IdentityProviderModel; -import org.keycloak.models.OAuthClientModel; -import org.keycloak.models.PasswordPolicy; -import org.keycloak.models.RealmModel; -import org.keycloak.models.RealmProvider; -import org.keycloak.models.RequiredCredentialModel; -import org.keycloak.models.RoleModel; -import org.keycloak.models.UserFederationProviderModel; -import org.keycloak.models.cache.RealmCache; -import org.keycloak.util.MultivaluedHashMap; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * @author Bill Burke - * @version $Revision: 1 $ - */ -public class CachedRealm { - - private String id; - private String name; - private boolean enabled; - private SslRequired sslRequired; - private boolean registrationAllowed; - private boolean registrationEmailAsUsername; - private boolean rememberMe; - private boolean verifyEmail; - private boolean passwordCredentialGrantAllowed; - private boolean resetPasswordAllowed; - private boolean identityFederationEnabled; - //--- brute force settings - private boolean bruteForceProtected; - private int maxFailureWaitSeconds; - private int minimumQuickLoginWaitSeconds; - private int waitIncrementSeconds; - private long quickLoginCheckMilliSeconds; - private int maxDeltaTimeSeconds; - private int failureFactor; - //--- end brute force settings - - private int ssoSessionIdleTimeout; - private int ssoSessionMaxLifespan; - private int accessTokenLifespan; - private int accessCodeLifespan; - private int accessCodeLifespanUserAction; - private int accessCodeLifespanLogin; - private int notBefore; - private PasswordPolicy passwordPolicy; - - private String publicKeyPem; - private String privateKeyPem; - private String certificatePem; - private String codeSecret; - - private String loginTheme; - private String accountTheme; - private String adminTheme; - private String emailTheme; - private String masterAdminApp; - - private List requiredCredentials = new ArrayList(); - private List userFederationProviders = new ArrayList(); - private List identityProviders = new ArrayList(); - - private Map browserSecurityHeaders = new HashMap(); - private Map smtpConfig = new HashMap(); - - private boolean eventsEnabled; - private long eventsExpiration; - private Set eventsListeners = new HashSet(); - private Set enabledEventTypes = new HashSet(); - private List defaultRoles = new LinkedList(); - private Map realmRoles = new HashMap(); - private Map applications = new HashMap(); - private Map clients = new HashMap(); - private boolean internationalizationEnabled; - private Set supportedLocales = new HashSet(); - private String defaultLocale; - private MultivaluedHashMap identityProviderMappers = new MultivaluedHashMap<>(); - - public CachedRealm() { - } - - public CachedRealm(RealmCache cache, RealmProvider delegate, RealmModel model) { - id = model.getId(); - name = model.getName(); - enabled = model.isEnabled(); - sslRequired = model.getSslRequired(); - registrationAllowed = model.isRegistrationAllowed(); - registrationEmailAsUsername = model.isRegistrationEmailAsUsername(); - rememberMe = model.isRememberMe(); - verifyEmail = model.isVerifyEmail(); - passwordCredentialGrantAllowed = model.isPasswordCredentialGrantAllowed(); - resetPasswordAllowed = model.isResetPasswordAllowed(); - identityFederationEnabled = model.isIdentityFederationEnabled(); - //--- brute force settings - bruteForceProtected = model.isBruteForceProtected(); - maxFailureWaitSeconds = model.getMaxFailureWaitSeconds(); - minimumQuickLoginWaitSeconds = model.getMinimumQuickLoginWaitSeconds(); - waitIncrementSeconds = model.getWaitIncrementSeconds(); - quickLoginCheckMilliSeconds = model.getQuickLoginCheckMilliSeconds(); - maxDeltaTimeSeconds = model.getMaxDeltaTimeSeconds(); - failureFactor = model.getFailureFactor(); - //--- end brute force settings - - ssoSessionIdleTimeout = model.getSsoSessionIdleTimeout(); - ssoSessionMaxLifespan = model.getSsoSessionMaxLifespan(); - accessTokenLifespan = model.getAccessTokenLifespan(); - accessCodeLifespan = model.getAccessCodeLifespan(); - accessCodeLifespanUserAction = model.getAccessCodeLifespanUserAction(); - accessCodeLifespanLogin = model.getAccessCodeLifespanLogin(); - notBefore = model.getNotBefore(); - passwordPolicy = model.getPasswordPolicy(); - - publicKeyPem = model.getPublicKeyPem(); - privateKeyPem = model.getPrivateKeyPem(); - certificatePem = model.getCertificatePem(); - codeSecret = model.getCodeSecret(); - - loginTheme = model.getLoginTheme(); - accountTheme = model.getAccountTheme(); - adminTheme = model.getAdminTheme(); - emailTheme = model.getEmailTheme(); - - requiredCredentials = model.getRequiredCredentials(); - userFederationProviders = model.getUserFederationProviders(); - - this.identityProviders = new ArrayList<>(); - - for (IdentityProviderModel identityProviderModel : model.getIdentityProviders()) { - this.identityProviders.add(new IdentityProviderModel(identityProviderModel)); - } - - for (IdentityProviderMapperModel mapper : model.getIdentityProviderMappers()) { - identityProviderMappers.add(mapper.getIdentityProviderAlias(), mapper); - } - - - - smtpConfig.putAll(model.getSmtpConfig()); - browserSecurityHeaders.putAll(model.getBrowserSecurityHeaders()); - - eventsEnabled = model.isEventsEnabled(); - eventsExpiration = model.getEventsExpiration(); - eventsListeners.addAll(model.getEventsListeners()); - enabledEventTypes.addAll(model.getEnabledEventTypes()); - defaultRoles.addAll(model.getDefaultRoles()); - masterAdminApp = model.getMasterAdminApp().getId(); - - for (RoleModel role : model.getRoles()) { - realmRoles.put(role.getName(), role.getId()); - CachedRole cachedRole = new CachedRealmRole(role, model); - cache.addCachedRole(cachedRole); - } - - for (ApplicationModel app : model.getApplications()) { - applications.put(app.getName(), app.getId()); - CachedApplication cachedApp = new CachedApplication(cache, delegate, model, app); - cache.addCachedApplication(cachedApp); - } - - for (OAuthClientModel client : model.getOAuthClients()) { - clients.put(client.getClientId(), client.getId()); - CachedOAuthClient cachedApp = new CachedOAuthClient(cache, delegate, model, client); - cache.addCachedOAuthClient(cachedApp); - } - - internationalizationEnabled = model.isInternationalizationEnabled(); - supportedLocales.addAll(model.getSupportedLocales()); - defaultLocale = model.getDefaultLocale(); - - } - - - public String getId() { - return id; - } - - public String getMasterAdminApp() { - return masterAdminApp; - } - - public String getName() { - return name; - } - - public List getDefaultRoles() { - return defaultRoles; - } - - public Map getRealmRoles() { - return realmRoles; - } - - public Map getApplications() { - return applications; - } - - public Map getClients() { - return clients; - } - - public boolean isEnabled() { - return enabled; - } - - public SslRequired getSslRequired() { - return sslRequired; - } - - public boolean isRegistrationAllowed() { - return registrationAllowed; - } - - public boolean isRegistrationEmailAsUsername() { - return registrationEmailAsUsername; - } - - public boolean isPasswordCredentialGrantAllowed() { - return passwordCredentialGrantAllowed; - } - - public boolean isRememberMe() { - return this.rememberMe; - } - - public boolean isBruteForceProtected() { - return bruteForceProtected; - } - - public int getMaxFailureWaitSeconds() { - return this.maxFailureWaitSeconds; - } - - public int getWaitIncrementSeconds() { - return this.waitIncrementSeconds; - } - - public int getMinimumQuickLoginWaitSeconds() { - return this.minimumQuickLoginWaitSeconds; - } - - public long getQuickLoginCheckMilliSeconds() { - return quickLoginCheckMilliSeconds; - } - - public int getMaxDeltaTimeSeconds() { - return maxDeltaTimeSeconds; - } - - public int getFailureFactor() { - return failureFactor; - } - - public boolean isVerifyEmail() { - return verifyEmail; - } - - public boolean isResetPasswordAllowed() { - return resetPasswordAllowed; - } - - public int getSsoSessionIdleTimeout() { - return ssoSessionIdleTimeout; - } - - public int getSsoSessionMaxLifespan() { - return ssoSessionMaxLifespan; - } - - public int getAccessTokenLifespan() { - return accessTokenLifespan; - } - - public int getAccessCodeLifespan() { - return accessCodeLifespan; - } - - public int getAccessCodeLifespanUserAction() { - return accessCodeLifespanUserAction; - } - public int getAccessCodeLifespanLogin() { - return accessCodeLifespanLogin; - } - - public String getPublicKeyPem() { - return publicKeyPem; - } - - public String getPrivateKeyPem() { - return privateKeyPem; - } - - public String getCodeSecret() { - return codeSecret; - } - - public List getRequiredCredentials() { - return requiredCredentials; - } - - public PasswordPolicy getPasswordPolicy() { - return passwordPolicy; - } - - public boolean isIdentityFederationEnabled() { - return identityFederationEnabled; - } - - public Map getSmtpConfig() { - return smtpConfig; - } - - public Map getBrowserSecurityHeaders() { - return browserSecurityHeaders; - } - - public String getLoginTheme() { - return loginTheme; - } - - public String getAccountTheme() { - return accountTheme; - } - - public String getAdminTheme() { - return this.adminTheme; - } - - public String getEmailTheme() { - return emailTheme; - } - - public int getNotBefore() { - return notBefore; - } - - public boolean isEventsEnabled() { - return eventsEnabled; - } - - public long getEventsExpiration() { - return eventsExpiration; - } - - public Set getEventsListeners() { - return eventsListeners; - } - - public Set getEnabledEventTypes() { - return enabledEventTypes; - } - - public List getUserFederationProviders() { - return userFederationProviders; - } - - public String getCertificatePem() { - return certificatePem; - } - - public List getIdentityProviders() { - return identityProviders; - } - - public boolean isInternationalizationEnabled() { - return internationalizationEnabled; - } - - public Set getSupportedLocales() { - return supportedLocales; - } - - public String getDefaultLocale() { - return defaultLocale; - } - - public MultivaluedHashMap getIdentityProviderMappers() { - return identityProviderMappers; - } -} +package org.keycloak.models.cache.entities; + +import org.keycloak.enums.SslRequired; +import org.keycloak.models.ClientModel; +import org.keycloak.models.IdentityProviderMapperModel; +import org.keycloak.models.IdentityProviderModel; +import org.keycloak.models.PasswordPolicy; +import org.keycloak.models.RealmModel; +import org.keycloak.models.RealmProvider; +import org.keycloak.models.RequiredCredentialModel; +import org.keycloak.models.RoleModel; +import org.keycloak.models.UserFederationProviderModel; +import org.keycloak.models.cache.RealmCache; +import org.keycloak.util.MultivaluedHashMap; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * @author Bill Burke + * @version $Revision: 1 $ + */ +public class CachedRealm { + + private String id; + private String name; + private boolean enabled; + private SslRequired sslRequired; + private boolean registrationAllowed; + private boolean registrationEmailAsUsername; + private boolean rememberMe; + private boolean verifyEmail; + private boolean passwordCredentialGrantAllowed; + private boolean resetPasswordAllowed; + private boolean identityFederationEnabled; + //--- brute force settings + private boolean bruteForceProtected; + private int maxFailureWaitSeconds; + private int minimumQuickLoginWaitSeconds; + private int waitIncrementSeconds; + private long quickLoginCheckMilliSeconds; + private int maxDeltaTimeSeconds; + private int failureFactor; + //--- end brute force settings + + private int ssoSessionIdleTimeout; + private int ssoSessionMaxLifespan; + private int accessTokenLifespan; + private int accessCodeLifespan; + private int accessCodeLifespanUserAction; + private int accessCodeLifespanLogin; + private int notBefore; + private PasswordPolicy passwordPolicy; + + private String publicKeyPem; + private String privateKeyPem; + private String certificatePem; + private String codeSecret; + + private String loginTheme; + private String accountTheme; + private String adminTheme; + private String emailTheme; + private String masterAdminApp; + + private List requiredCredentials = new ArrayList(); + private List userFederationProviders = new ArrayList(); + private List identityProviders = new ArrayList(); + + private Map browserSecurityHeaders = new HashMap(); + private Map smtpConfig = new HashMap(); + + private boolean eventsEnabled; + private long eventsExpiration; + private Set eventsListeners = new HashSet(); + private Set enabledEventTypes = new HashSet(); + private List defaultRoles = new LinkedList(); + private Map realmRoles = new HashMap(); + private Map applications = new HashMap(); + private Map clients = new HashMap(); + private boolean internationalizationEnabled; + private Set supportedLocales = new HashSet(); + private String defaultLocale; + private MultivaluedHashMap identityProviderMappers = new MultivaluedHashMap<>(); + + public CachedRealm() { + } + + public CachedRealm(RealmCache cache, RealmProvider delegate, RealmModel model) { + id = model.getId(); + name = model.getName(); + enabled = model.isEnabled(); + sslRequired = model.getSslRequired(); + registrationAllowed = model.isRegistrationAllowed(); + registrationEmailAsUsername = model.isRegistrationEmailAsUsername(); + rememberMe = model.isRememberMe(); + verifyEmail = model.isVerifyEmail(); + passwordCredentialGrantAllowed = model.isPasswordCredentialGrantAllowed(); + resetPasswordAllowed = model.isResetPasswordAllowed(); + identityFederationEnabled = model.isIdentityFederationEnabled(); + //--- brute force settings + bruteForceProtected = model.isBruteForceProtected(); + maxFailureWaitSeconds = model.getMaxFailureWaitSeconds(); + minimumQuickLoginWaitSeconds = model.getMinimumQuickLoginWaitSeconds(); + waitIncrementSeconds = model.getWaitIncrementSeconds(); + quickLoginCheckMilliSeconds = model.getQuickLoginCheckMilliSeconds(); + maxDeltaTimeSeconds = model.getMaxDeltaTimeSeconds(); + failureFactor = model.getFailureFactor(); + //--- end brute force settings + + ssoSessionIdleTimeout = model.getSsoSessionIdleTimeout(); + ssoSessionMaxLifespan = model.getSsoSessionMaxLifespan(); + accessTokenLifespan = model.getAccessTokenLifespan(); + accessCodeLifespan = model.getAccessCodeLifespan(); + accessCodeLifespanUserAction = model.getAccessCodeLifespanUserAction(); + accessCodeLifespanLogin = model.getAccessCodeLifespanLogin(); + notBefore = model.getNotBefore(); + passwordPolicy = model.getPasswordPolicy(); + + publicKeyPem = model.getPublicKeyPem(); + privateKeyPem = model.getPrivateKeyPem(); + certificatePem = model.getCertificatePem(); + codeSecret = model.getCodeSecret(); + + loginTheme = model.getLoginTheme(); + accountTheme = model.getAccountTheme(); + adminTheme = model.getAdminTheme(); + emailTheme = model.getEmailTheme(); + + requiredCredentials = model.getRequiredCredentials(); + userFederationProviders = model.getUserFederationProviders(); + + this.identityProviders = new ArrayList<>(); + + for (IdentityProviderModel identityProviderModel : model.getIdentityProviders()) { + this.identityProviders.add(new IdentityProviderModel(identityProviderModel)); + } + + for (IdentityProviderMapperModel mapper : model.getIdentityProviderMappers()) { + identityProviderMappers.add(mapper.getIdentityProviderAlias(), mapper); + } + + + + smtpConfig.putAll(model.getSmtpConfig()); + browserSecurityHeaders.putAll(model.getBrowserSecurityHeaders()); + + eventsEnabled = model.isEventsEnabled(); + eventsExpiration = model.getEventsExpiration(); + eventsListeners.addAll(model.getEventsListeners()); + enabledEventTypes.addAll(model.getEnabledEventTypes()); + defaultRoles.addAll(model.getDefaultRoles()); + masterAdminApp = model.getMasterAdminClient().getId(); + + for (RoleModel role : model.getRoles()) { + realmRoles.put(role.getName(), role.getId()); + CachedRole cachedRole = new CachedRealmRole(role, model); + cache.addCachedRole(cachedRole); + } + + for (ClientModel app : model.getClients()) { + applications.put(app.getClientId(), app.getId()); + CachedApplication cachedApp = new CachedApplication(cache, delegate, model, app); + cache.addCachedApplication(cachedApp); + } + + internationalizationEnabled = model.isInternationalizationEnabled(); + supportedLocales.addAll(model.getSupportedLocales()); + defaultLocale = model.getDefaultLocale(); + + } + + + public String getId() { + return id; + } + + public String getMasterAdminApp() { + return masterAdminApp; + } + + public String getName() { + return name; + } + + public List getDefaultRoles() { + return defaultRoles; + } + + public Map getRealmRoles() { + return realmRoles; + } + + public Map getApplications() { + return applications; + } + + public Map getClients() { + return clients; + } + + public boolean isEnabled() { + return enabled; + } + + public SslRequired getSslRequired() { + return sslRequired; + } + + public boolean isRegistrationAllowed() { + return registrationAllowed; + } + + public boolean isRegistrationEmailAsUsername() { + return registrationEmailAsUsername; + } + + public boolean isPasswordCredentialGrantAllowed() { + return passwordCredentialGrantAllowed; + } + + public boolean isRememberMe() { + return this.rememberMe; + } + + public boolean isBruteForceProtected() { + return bruteForceProtected; + } + + public int getMaxFailureWaitSeconds() { + return this.maxFailureWaitSeconds; + } + + public int getWaitIncrementSeconds() { + return this.waitIncrementSeconds; + } + + public int getMinimumQuickLoginWaitSeconds() { + return this.minimumQuickLoginWaitSeconds; + } + + public long getQuickLoginCheckMilliSeconds() { + return quickLoginCheckMilliSeconds; + } + + public int getMaxDeltaTimeSeconds() { + return maxDeltaTimeSeconds; + } + + public int getFailureFactor() { + return failureFactor; + } + + public boolean isVerifyEmail() { + return verifyEmail; + } + + public boolean isResetPasswordAllowed() { + return resetPasswordAllowed; + } + + public int getSsoSessionIdleTimeout() { + return ssoSessionIdleTimeout; + } + + public int getSsoSessionMaxLifespan() { + return ssoSessionMaxLifespan; + } + + public int getAccessTokenLifespan() { + return accessTokenLifespan; + } + + public int getAccessCodeLifespan() { + return accessCodeLifespan; + } + + public int getAccessCodeLifespanUserAction() { + return accessCodeLifespanUserAction; + } + public int getAccessCodeLifespanLogin() { + return accessCodeLifespanLogin; + } + + public String getPublicKeyPem() { + return publicKeyPem; + } + + public String getPrivateKeyPem() { + return privateKeyPem; + } + + public String getCodeSecret() { + return codeSecret; + } + + public List getRequiredCredentials() { + return requiredCredentials; + } + + public PasswordPolicy getPasswordPolicy() { + return passwordPolicy; + } + + public boolean isIdentityFederationEnabled() { + return identityFederationEnabled; + } + + public Map getSmtpConfig() { + return smtpConfig; + } + + public Map getBrowserSecurityHeaders() { + return browserSecurityHeaders; + } + + public String getLoginTheme() { + return loginTheme; + } + + public String getAccountTheme() { + return accountTheme; + } + + public String getAdminTheme() { + return this.adminTheme; + } + + public String getEmailTheme() { + return emailTheme; + } + + public int getNotBefore() { + return notBefore; + } + + public boolean isEventsEnabled() { + return eventsEnabled; + } + + public long getEventsExpiration() { + return eventsExpiration; + } + + public Set getEventsListeners() { + return eventsListeners; + } + + public Set getEnabledEventTypes() { + return enabledEventTypes; + } + + public List getUserFederationProviders() { + return userFederationProviders; + } + + public String getCertificatePem() { + return certificatePem; + } + + public List getIdentityProviders() { + return identityProviders; + } + + public boolean isInternationalizationEnabled() { + return internationalizationEnabled; + } + + public Set getSupportedLocales() { + return supportedLocales; + } + + public String getDefaultLocale() { + return defaultLocale; + } + + public MultivaluedHashMap getIdentityProviderMappers() { + return identityProviderMappers; + } +} diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/ApplicationAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/ApplicationAdapter.java deleted file mode 100755 index dd1603c6af..0000000000 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/ApplicationAdapter.java +++ /dev/null @@ -1,308 +0,0 @@ -package org.keycloak.models.jpa; - -import org.keycloak.models.ApplicationModel; -import org.keycloak.models.ClientModel; -import org.keycloak.models.KeycloakSession; -import org.keycloak.models.RealmModel; -import org.keycloak.models.RoleContainerModel; -import org.keycloak.models.RoleModel; -import org.keycloak.models.jpa.entities.ApplicationEntity; -import org.keycloak.models.jpa.entities.IdentityProviderEntity; -import org.keycloak.models.jpa.entities.RoleEntity; -import org.keycloak.models.utils.KeycloakModelUtils; - -import javax.persistence.EntityManager; -import javax.persistence.TypedQuery; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * @author Bill Burke - * @version $Revision: 1 $ - */ -public class ApplicationAdapter extends ClientAdapter implements ApplicationModel { - - protected EntityManager em; - protected KeycloakSession session; - protected ApplicationEntity applicationEntity; - - public ApplicationAdapter(RealmModel realm, EntityManager em, KeycloakSession session, ApplicationEntity applicationEntity) { - super(realm, applicationEntity, em); - this.session = session; - this.realm = realm; - this.em = em; - this.applicationEntity = applicationEntity; - } - - @Override - public void updateApplication() { - em.flush(); - } - - @Override - public String getName() { - return entity.getName(); - } - - @Override - public void setName(String name) { - entity.setName(name); - } - - @Override - public boolean isSurrogateAuthRequired() { - return applicationEntity.isSurrogateAuthRequired(); - } - - @Override - public void setSurrogateAuthRequired(boolean surrogateAuthRequired) { - applicationEntity.setSurrogateAuthRequired(surrogateAuthRequired); - } - - @Override - public String getManagementUrl() { - return applicationEntity.getManagementUrl(); - } - - @Override - public void setManagementUrl(String url) { - applicationEntity.setManagementUrl(url); - } - - @Override - public String getBaseUrl() { - return applicationEntity.getBaseUrl(); - } - - @Override - public void setBaseUrl(String url) { - applicationEntity.setBaseUrl(url); - } - - @Override - public boolean isBearerOnly() { - return applicationEntity.isBearerOnly(); - } - - @Override - public void setBearerOnly(boolean only) { - applicationEntity.setBearerOnly(only); - } - - @Override - public boolean isDirectGrantsOnly() { - return false; // applications can't be grant only - } - - @Override - public void setDirectGrantsOnly(boolean flag) { - // applications can't be grant only - } - - @Override - public RoleModel getRole(String name) { - TypedQuery query = em.createNamedQuery("getAppRoleByName", RoleEntity.class); - query.setParameter("name", name); - query.setParameter("application", entity); - List roles = query.getResultList(); - if (roles.size() == 0) return null; - return new RoleAdapter(realm, em, roles.get(0)); - } - - @Override - public RoleModel addRole(String name) { - return this.addRole(KeycloakModelUtils.generateId(), name); - } - - @Override - public RoleModel addRole(String id, String name) { - RoleEntity roleEntity = new RoleEntity(); - roleEntity.setId(id); - roleEntity.setName(name); - roleEntity.setApplication(applicationEntity); - roleEntity.setApplicationRole(true); - roleEntity.setRealmId(realm.getId()); - em.persist(roleEntity); - applicationEntity.getRoles().add(roleEntity); - em.flush(); - return new RoleAdapter(realm, em, roleEntity); - } - - @Override - public boolean removeRole(RoleModel roleModel) { - if (roleModel == null) { - return false; - } - if (!roleModel.getContainer().equals(this)) return false; - - session.users().preRemove(getRealm(), roleModel); - RoleEntity role = RoleAdapter.toRoleEntity(roleModel, em); - if (!role.isApplicationRole()) return false; - - - applicationEntity.getRoles().remove(role); - applicationEntity.getDefaultRoles().remove(role); - em.createNativeQuery("delete from COMPOSITE_ROLE where CHILD_ROLE = :role").setParameter("role", role).executeUpdate(); - em.createNamedQuery("deleteScopeMappingByRole").setParameter("role", role).executeUpdate(); - role.setApplication(null); - em.flush(); - em.remove(role); - em.flush(); - - return true; - } - - @Override - public Set getRoles() { - Set list = new HashSet(); - Collection roles = applicationEntity.getRoles(); - if (roles == null) return list; - for (RoleEntity entity : roles) { - list.add(new RoleAdapter(realm, em, entity)); - } - return list; - } - - @Override - public boolean hasScope(RoleModel role) { - if (super.hasScope(role)) { - return true; - } - Set roles = getRoles(); - if (roles.contains(role)) return true; - - for (RoleModel mapping : roles) { - if (mapping.hasRole(role)) return true; - } - return false; - } - - @Override - public Set getApplicationScopeMappings(ClientModel client) { - Set roleMappings = client.getScopeMappings(); - - Set appRoles = new HashSet(); - for (RoleModel role : roleMappings) { - RoleContainerModel container = role.getContainer(); - if (container instanceof RealmModel) { - } else { - ApplicationModel app = (ApplicationModel)container; - if (app.getId().equals(getId())) { - appRoles.add(role); - } - } - } - - return appRoles; - } - - - - - @Override - public List getDefaultRoles() { - Collection entities = applicationEntity.getDefaultRoles(); - List roles = new ArrayList(); - if (entities == null) return roles; - for (RoleEntity entity : entities) { - roles.add(entity.getName()); - } - return roles; - } - - @Override - public void addDefaultRole(String name) { - RoleModel role = getRole(name); - if (role == null) { - role = addRole(name); - } - Collection entities = applicationEntity.getDefaultRoles(); - for (RoleEntity entity : entities) { - if (entity.getId().equals(role.getId())) { - return; - } - } - RoleEntity roleEntity = RoleAdapter.toRoleEntity(role, em); - entities.add(roleEntity); - em.flush(); - } - - @Override - public void updateDefaultRoles(String[] defaultRoles) { - Collection entities = applicationEntity.getDefaultRoles(); - Set already = new HashSet(); - List remove = new ArrayList(); - for (RoleEntity rel : entities) { - if (!contains(rel.getName(), defaultRoles)) { - remove.add(rel); - } else { - already.add(rel.getName()); - } - } - for (RoleEntity entity : remove) { - entities.remove(entity); - } - em.flush(); - for (String roleName : defaultRoles) { - if (!already.contains(roleName)) { - addDefaultRole(roleName); - } - } - em.flush(); - } - - @Override - public int getNodeReRegistrationTimeout() { - return applicationEntity.getNodeReRegistrationTimeout(); - } - - @Override - public void setNodeReRegistrationTimeout(int timeout) { - applicationEntity.setNodeReRegistrationTimeout(timeout); - } - - @Override - public Map getRegisteredNodes() { - return applicationEntity.getRegisteredNodes(); - } - - @Override - public void registerNode(String nodeHost, int registrationTime) { - Map currentNodes = getRegisteredNodes(); - currentNodes.put(nodeHost, registrationTime); - em.flush(); - } - - @Override - public void unregisterNode(String nodeHost) { - Map currentNodes = getRegisteredNodes(); - currentNodes.remove(nodeHost); - em.flush(); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || !(o instanceof ApplicationModel)) return false; - - ApplicationModel that = (ApplicationModel) o; - return that.getId().equals(getId()); - } - - @Override - public int hashCode() { - return getId().hashCode(); - } - - public String toString() { - return getName(); - } - - ApplicationEntity getJpaEntity() { - return applicationEntity; - } -} diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/ClientAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/ClientAdapter.java index bd4430827a..b04a92c15e 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/ClientAdapter.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/ClientAdapter.java @@ -1,9 +1,8 @@ package org.keycloak.models.jpa; -import org.keycloak.models.ApplicationModel; -import org.keycloak.models.ClientIdentityProviderMappingModel; import org.keycloak.models.ClientModel; -import org.keycloak.models.OAuthClientModel; +import org.keycloak.models.ClientIdentityProviderMappingModel; +import org.keycloak.models.KeycloakSession; import org.keycloak.models.ProtocolMapperModel; import org.keycloak.models.RealmModel; import org.keycloak.models.RoleContainerModel; @@ -22,8 +21,6 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; @@ -32,15 +29,18 @@ import java.util.Set; * @author Bill Burke * @version $Revision: 1 $ */ -public abstract class ClientAdapter implements ClientModel { - protected ClientEntity entity; +public class ClientAdapter implements ClientModel { + + protected KeycloakSession session; protected RealmModel realm; protected EntityManager em; + protected ClientEntity entity; - public ClientAdapter(RealmModel realm, ClientEntity entity, EntityManager em) { + public ClientAdapter(RealmModel realm, EntityManager em, KeycloakSession session, ClientEntity entity) { + this.session = session; this.realm = realm; - this.entity = entity; this.em = em; + this.entity = entity; } public ClientEntity getEntity() { @@ -57,11 +57,6 @@ public abstract class ClientAdapter implements ClientModel { return realm; } - @Override - public String getClientId() { - return entity.getName(); - } - @Override public boolean isEnabled() { return entity.isEnabled(); @@ -177,7 +172,7 @@ public abstract class ClientAdapter implements ClientModel { public Set getRealmScopeMappings() { Set roleMappings = getScopeMappings(); - Set appRoles = new HashSet(); + Set appRoles = new HashSet<>(); for (RoleModel role : roleMappings) { RoleContainerModel container = role.getContainer(); if (container instanceof RealmModel) { @@ -190,8 +185,6 @@ public abstract class ClientAdapter implements ClientModel { return appRoles; } - - @Override public Set getScopeMappings() { TypedQuery query = em.createNamedQuery("clientScopeMappingIds", String.class); @@ -236,32 +229,6 @@ public abstract class ClientAdapter implements ClientModel { return query; } - @Override - public boolean hasScope(RoleModel role) { - if (isFullScopeAllowed()) return true; - Set roles = getScopeMappings(); - if (roles.contains(role)) return true; - - for (RoleModel mapping : roles) { - if (mapping.hasRole(role)) return true; - } - return false; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!this.getClass().equals(o.getClass())) return false; - - ClientAdapter that = (ClientAdapter) o; - return that.getId().equals(getId()); - } - - @Override - public int hashCode() { - return entity.getId().hashCode(); - } - @Override public String getProtocol() { return entity.getProtocol(); @@ -281,7 +248,7 @@ public abstract class ClientAdapter implements ClientModel { @Override public void removeAttribute(String name) { - entity.getAttributes().remove(name); + entity.getAttributes().remove(name); } @Override @@ -291,7 +258,7 @@ public abstract class ClientAdapter implements ClientModel { @Override public Map getAttributes() { - Map copy = new HashMap(); + Map copy = new HashMap<>(); copy.putAll(entity.getAttributes()); return copy; } @@ -299,8 +266,8 @@ public abstract class ClientAdapter implements ClientModel { @Override public void updateIdentityProviders(List identityProviders) { Collection entities = entity.getIdentityProviders(); - Set already = new HashSet(); - List remove = new ArrayList(); + Set already = new HashSet<>(); + List remove = new ArrayList<>(); for (ClientIdentityProviderMappingEntity entity : entities) { IdentityProviderEntity identityProvider = entity.getIdentityProvider(); @@ -500,4 +467,282 @@ public abstract class ClientAdapter implements ClientModel { mapping.setConfig(config); return mapping; } + + @Override + public void updateClient() { + em.flush(); + } + + @Override + public String getClientId() { + return entity.getClientId(); + } + + @Override + public void setClientId(String clientId) { + entity.setClientId(clientId); + } + + @Override + public boolean isSurrogateAuthRequired() { + return entity.isSurrogateAuthRequired(); + } + + @Override + public void setSurrogateAuthRequired(boolean surrogateAuthRequired) { + entity.setSurrogateAuthRequired(surrogateAuthRequired); + } + + @Override + public String getManagementUrl() { + return entity.getManagementUrl(); + } + + @Override + public void setManagementUrl(String url) { + entity.setManagementUrl(url); + } + + @Override + public String getBaseUrl() { + return entity.getBaseUrl(); + } + + @Override + public void setBaseUrl(String url) { + entity.setBaseUrl(url); + } + + @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 isDirectGrantsOnly() { + return entity.isDirectGrantsOnly(); + } + + @Override + public void setDirectGrantsOnly(boolean flag) { + entity.setDirectGrantsOnly(flag); + } + + @Override + public RoleModel getRole(String name) { + TypedQuery query = em.createNamedQuery("getAppRoleByName", RoleEntity.class); + query.setParameter("name", name); + query.setParameter("application", entity); + List roles = query.getResultList(); + if (roles.size() == 0) return null; + return new RoleAdapter(realm, em, roles.get(0)); + } + + @Override + public RoleModel addRole(String name) { + return this.addRole(KeycloakModelUtils.generateId(), name); + } + + @Override + public RoleModel addRole(String id, String name) { + RoleEntity roleEntity = new RoleEntity(); + roleEntity.setId(id); + roleEntity.setName(name); + roleEntity.setApplication(entity); + roleEntity.setApplicationRole(true); + roleEntity.setRealmId(realm.getId()); + em.persist(roleEntity); + entity.getRoles().add(roleEntity); + em.flush(); + return new RoleAdapter(realm, em, roleEntity); + } + + @Override + public boolean removeRole(RoleModel roleModel) { + if (roleModel == null) { + return false; + } + if (!roleModel.getContainer().equals(this)) return false; + + session.users().preRemove(getRealm(), roleModel); + RoleEntity role = RoleAdapter.toRoleEntity(roleModel, em); + if (!role.isApplicationRole()) return false; + + entity.getRoles().remove(role); + entity.getDefaultRoles().remove(role); + em.createNativeQuery("delete from COMPOSITE_ROLE where CHILD_ROLE = :role").setParameter("role", role).executeUpdate(); + em.createNamedQuery("deleteScopeMappingByRole").setParameter("role", role).executeUpdate(); + role.setApplication(null); + em.flush(); + em.remove(role); + em.flush(); + + return true; + } + + @Override + public Set getRoles() { + Set list = new HashSet(); + Collection roles = entity.getRoles(); + if (roles == null) return list; + for (RoleEntity entity : roles) { + list.add(new RoleAdapter(realm, em, entity)); + } + return list; + } + + @Override + public boolean hasScope(RoleModel role) { + if (isFullScopeAllowed()) return true; + Set roles = getScopeMappings(); + if (roles.contains(role)) return true; + + for (RoleModel mapping : roles) { + if (mapping.hasRole(role)) return true; + } + roles = getRoles(); + if (roles.contains(role)) return true; + + for (RoleModel mapping : roles) { + if (mapping.hasRole(role)) return true; + } + return false; + } + + @Override + public Set getClientScopeMappings(ClientModel client) { + Set roleMappings = client.getScopeMappings(); + + Set appRoles = new HashSet(); + for (RoleModel role : roleMappings) { + RoleContainerModel container = role.getContainer(); + if (container instanceof RealmModel) { + } else { + ClientModel app = (ClientModel)container; + if (app.getId().equals(getId())) { + appRoles.add(role); + } + } + } + + return appRoles; + } + + + + + @Override + public List getDefaultRoles() { + Collection entities = entity.getDefaultRoles(); + List roles = new ArrayList(); + if (entities == null) return roles; + for (RoleEntity entity : entities) { + roles.add(entity.getName()); + } + return roles; + } + + @Override + public void addDefaultRole(String name) { + RoleModel role = getRole(name); + if (role == null) { + role = addRole(name); + } + Collection entities = entity.getDefaultRoles(); + for (RoleEntity entity : entities) { + if (entity.getId().equals(role.getId())) { + return; + } + } + RoleEntity roleEntity = RoleAdapter.toRoleEntity(role, em); + entities.add(roleEntity); + em.flush(); + } + + @Override + public void updateDefaultRoles(String[] defaultRoles) { + Collection entities = entity.getDefaultRoles(); + Set already = new HashSet(); + List remove = new ArrayList(); + for (RoleEntity rel : entities) { + if (!contains(rel.getName(), defaultRoles)) { + remove.add(rel); + } else { + already.add(rel.getName()); + } + } + for (RoleEntity entity : remove) { + entities.remove(entity); + } + em.flush(); + for (String roleName : defaultRoles) { + if (!already.contains(roleName)) { + addDefaultRole(roleName); + } + } + em.flush(); + } + + @Override + public int getNodeReRegistrationTimeout() { + return entity.getNodeReRegistrationTimeout(); + } + + @Override + public void setNodeReRegistrationTimeout(int timeout) { + entity.setNodeReRegistrationTimeout(timeout); + } + + @Override + public Map getRegisteredNodes() { + return entity.getRegisteredNodes(); + } + + @Override + public void registerNode(String nodeHost, int registrationTime) { + Map currentNodes = getRegisteredNodes(); + currentNodes.put(nodeHost, registrationTime); + em.flush(); + } + + @Override + public void unregisterNode(String nodeHost) { + Map currentNodes = getRegisteredNodes(); + currentNodes.remove(nodeHost); + em.flush(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || !(o instanceof ClientModel)) return false; + + ClientModel that = (ClientModel) o; + return that.getId().equals(getId()); + } + + @Override + public int hashCode() { + return getId().hashCode(); + } + + public String toString() { + return getClientId(); + } + } diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaRealmProvider.java b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaRealmProvider.java index 3091cc9213..f88767040a 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaRealmProvider.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaRealmProvider.java @@ -1,13 +1,11 @@ package org.keycloak.models.jpa; -import org.keycloak.models.ApplicationModel; +import org.keycloak.models.ClientModel; import org.keycloak.models.KeycloakSession; -import org.keycloak.models.OAuthClientModel; import org.keycloak.models.RealmModel; import org.keycloak.models.RealmProvider; import org.keycloak.models.RoleModel; -import org.keycloak.models.jpa.entities.ApplicationEntity; -import org.keycloak.models.jpa.entities.OAuthClientEntity; +import org.keycloak.models.jpa.entities.ClientEntity; import org.keycloak.models.jpa.entities.RealmEntity; import org.keycloak.models.jpa.entities.RoleEntity; import org.keycloak.models.utils.KeycloakModelUtils; @@ -93,12 +91,8 @@ public class JpaRealmProvider implements RealmProvider { RealmAdapter adapter = new RealmAdapter(session, em, realm); session.users().preRemove(adapter); - for (ApplicationEntity a : new LinkedList(realm.getApplications())) { - adapter.removeApplication(a.getId()); - } - - for (OAuthClientModel oauth : adapter.getOAuthClients()) { - adapter.removeOAuthClient(oauth.getId()); + for (ClientEntity a : new LinkedList<>(realm.getApplications())) { + adapter.removeClient(a.getId()); } em.remove(realm); @@ -118,21 +112,12 @@ public class JpaRealmProvider implements RealmProvider { } @Override - public ApplicationModel getApplicationById(String id, RealmModel realm) { - ApplicationEntity app = em.find(ApplicationEntity.class, id); + public ClientModel getClientById(String id, RealmModel realm) { + ClientEntity app = em.find(ClientEntity.class, id); // Check if application belongs to this realm if (app == null || !realm.getId().equals(app.getRealm().getId())) return null; - return new ApplicationAdapter(realm, em, session, app); - } - - @Override - public OAuthClientModel getOAuthClientById(String id, RealmModel realm) { - OAuthClientEntity client = em.find(OAuthClientEntity.class, id); - - // Check if client belongs to this realm - if (client == null || !realm.getId().equals(client.getRealm().getId())) return null; - return new OAuthClientAdapter(realm, client, em); + return new ClientAdapter(realm, em, session, app); } } diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProvider.java b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProvider.java index 2b00c1cc7a..07d3f6f910 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProvider.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProvider.java @@ -1,6 +1,6 @@ package org.keycloak.models.jpa; -import org.keycloak.models.ApplicationModel; +import org.keycloak.models.ClientModel; import org.keycloak.models.CredentialValidationOutput; import org.keycloak.models.FederatedIdentityModel; import org.keycloak.models.KeycloakSession; @@ -61,7 +61,7 @@ public class JpaUserProvider implements UserProvider { userModel.grantRole(realm.getRole(r)); } - for (ApplicationModel application : realm.getApplications()) { + for (ClientModel application : realm.getClients()) { for (String r : application.getDefaultRoles()) { userModel.grantRole(application.getRole(r)); } diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/OAuthClientAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/OAuthClientAdapter.java deleted file mode 100755 index 22791630c9..0000000000 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/OAuthClientAdapter.java +++ /dev/null @@ -1,52 +0,0 @@ -package org.keycloak.models.jpa; - -import org.keycloak.models.OAuthClientModel; -import org.keycloak.models.RealmModel; -import org.keycloak.models.jpa.entities.OAuthClientEntity; - -import javax.persistence.EntityManager; - -/** - * @author Bill Burke - * @version $Revision: 1 $ - */ -public class OAuthClientAdapter extends ClientAdapter implements OAuthClientModel { - - protected final OAuthClientEntity oAuthClientEntity; - - public OAuthClientAdapter(RealmModel realm, OAuthClientEntity entity, EntityManager em) { - super(realm, entity, em); - oAuthClientEntity = entity; - } - - @Override - public void setClientId(String id) { - entity.setName(id); - - } - - @Override - public boolean isDirectGrantsOnly() { - return oAuthClientEntity.isDirectGrantsOnly(); - } - - @Override - public void setDirectGrantsOnly(boolean flag) { - oAuthClientEntity.setDirectGrantsOnly(flag); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || !(o instanceof OAuthClientModel)) return false; - - OAuthClientModel that = (OAuthClientModel) o; - return that.getId().equals(getId()); - } - - @Override - public int hashCode() { - return getId().hashCode(); - } - -} diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java index 1f45e48371..4370165ff5 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java @@ -1,1415 +1,1325 @@ -package org.keycloak.models.jpa; - -import org.keycloak.enums.SslRequired; -import org.keycloak.models.ApplicationModel; -import org.keycloak.models.ClientModel; -import org.keycloak.models.IdentityProviderMapperModel; -import org.keycloak.models.IdentityProviderModel; -import org.keycloak.models.KeycloakSession; -import org.keycloak.models.OAuthClientModel; -import org.keycloak.models.PasswordPolicy; -import org.keycloak.models.ProtocolMapperModel; -import org.keycloak.models.RealmModel; -import org.keycloak.models.RequiredCredentialModel; -import org.keycloak.models.RoleModel; -import org.keycloak.models.UserFederationProviderModel; -import org.keycloak.models.jpa.entities.ApplicationEntity; -import org.keycloak.models.jpa.entities.IdentityProviderEntity; -import org.keycloak.models.jpa.entities.IdentityProviderMapperEntity; -import org.keycloak.models.jpa.entities.OAuthClientEntity; -import org.keycloak.models.jpa.entities.RealmAttributeEntity; -import org.keycloak.models.jpa.entities.RealmEntity; -import org.keycloak.models.jpa.entities.RequiredCredentialEntity; -import org.keycloak.models.jpa.entities.RoleEntity; -import org.keycloak.models.jpa.entities.UserFederationProviderEntity; -import org.keycloak.models.utils.KeycloakModelUtils; - -import javax.persistence.EntityManager; -import javax.persistence.TypedQuery; -import java.security.Key; -import java.security.PrivateKey; -import java.security.PublicKey; -import java.security.cert.X509Certificate; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * @author Bill Burke - * @version $Revision: 1 $ - */ -public class RealmAdapter implements RealmModel { - protected RealmEntity realm; - protected EntityManager em; - protected volatile transient PublicKey publicKey; - protected volatile transient PrivateKey privateKey; - protected volatile transient X509Certificate certificate; - protected volatile transient Key codeSecretKey; - protected KeycloakSession session; - private PasswordPolicy passwordPolicy; - - public RealmAdapter(KeycloakSession session, EntityManager em, RealmEntity realm) { - this.session = session; - this.em = em; - this.realm = realm; - } - - public RealmEntity getEntity() { - return realm; - } - - @Override - public String getId() { - return realm.getId(); - } - - @Override - public String getName() { - return realm.getName(); - } - - @Override - public void setName(String name) { - realm.setName(name); - em.flush(); - } - - @Override - public boolean isEnabled() { - return realm.isEnabled(); - } - - @Override - public void setEnabled(boolean enabled) { - realm.setEnabled(enabled); - em.flush(); - } - - @Override - public SslRequired getSslRequired() { - return realm.getSslRequired() != null ? SslRequired.valueOf(realm.getSslRequired()) : null; - } - - @Override - public void setSslRequired(SslRequired sslRequired) { - realm.setSslRequired(sslRequired.name()); - em.flush(); - } - - @Override - public boolean isPasswordCredentialGrantAllowed() { - return realm.isPasswordCredentialGrantAllowed(); - } - - @Override - public void setPasswordCredentialGrantAllowed(boolean passwordCredentialGrantAllowed) { - realm.setPasswordCredentialGrantAllowed(passwordCredentialGrantAllowed); - em.flush(); - } - - @Override - public boolean isRegistrationAllowed() { - return realm.isRegistrationAllowed(); - } - - @Override - public void setRegistrationAllowed(boolean registrationAllowed) { - realm.setRegistrationAllowed(registrationAllowed); - em.flush(); - } - - @Override - public boolean isRegistrationEmailAsUsername() { - return realm.isRegistrationEmailAsUsername(); - } - - @Override - public void setRegistrationEmailAsUsername(boolean registrationEmailAsUsername) { - realm.setRegistrationEmailAsUsername(registrationEmailAsUsername); - em.flush(); - } - - @Override - public boolean isRememberMe() { - return realm.isRememberMe(); - } - - @Override - public void setRememberMe(boolean rememberMe) { - realm.setRememberMe(rememberMe); - em.flush(); - } - - public void setAttribute(String name, String value) { - for (RealmAttributeEntity attr : realm.getAttributes()) { - if (attr.getName().equals(name)) { - attr.setValue(value); - return; - } - } - RealmAttributeEntity attr = new RealmAttributeEntity(); - attr.setName(name); - attr.setValue(value); - attr.setRealm(realm); - em.persist(attr); - realm.getAttributes().add(attr); - } - - public void setAttribute(String name, Boolean value) { - setAttribute(name, value.toString()); - } - - public void setAttribute(String name, Integer value) { - setAttribute(name, value.toString()); - } - - public void setAttribute(String name, Long value) { - setAttribute(name, value.toString()); - } - - public void removeAttribute(String name) { - Iterator it = realm.getAttributes().iterator(); - while (it.hasNext()) { - RealmAttributeEntity attr = it.next(); - if (attr.getName().equals(name)) { - it.remove(); - em.remove(attr); - } - } - } - - public String getAttribute(String name) { - for (RealmAttributeEntity attr : realm.getAttributes()) { - if (attr.getName().equals(name)) { - return attr.getValue(); - } - } - return null; - } - - public Integer getAttribute(String name, Integer defaultValue) { - String v = getAttribute(name); - return v != null ? Integer.parseInt(v) : defaultValue; - - } - - public Long getAttribute(String name, Long defaultValue) { - String v = getAttribute(name); - return v != null ? Long.parseLong(v) : defaultValue; - - } - - public Boolean getAttribute(String name, Boolean defaultValue) { - String v = getAttribute(name); - return v != null ? Boolean.parseBoolean(v) : defaultValue; - - } - - public Map getAttributes() { - // should always return a copy - Map result = new HashMap(); - for (RealmAttributeEntity attr : realm.getAttributes()) { - result.put(attr.getName(), attr.getValue()); - } - return result; - } - @Override - public boolean isBruteForceProtected() { - return getAttribute("bruteForceProtected", false); - } - - @Override - public void setBruteForceProtected(boolean value) { - setAttribute("bruteForceProtected", value); - } - - @Override - public int getMaxFailureWaitSeconds() { - return getAttribute("maxFailureWaitSeconds", 0); - } - - @Override - public void setMaxFailureWaitSeconds(int val) { - setAttribute("maxFailureWaitSeconds", val); - } - - @Override - public int getWaitIncrementSeconds() { - return getAttribute("waitIncrementSeconds", 0); - } - - @Override - public void setWaitIncrementSeconds(int val) { - setAttribute("waitIncrementSeconds", val); - } - - @Override - public long getQuickLoginCheckMilliSeconds() { - return getAttribute("quickLoginCheckMilliSeconds", 0l); - } - - @Override - public void setQuickLoginCheckMilliSeconds(long val) { - setAttribute("quickLoginCheckMilliSeconds", val); - } - - @Override - public int getMinimumQuickLoginWaitSeconds() { - return getAttribute("minimumQuickLoginWaitSeconds", 0); - } - - @Override - public void setMinimumQuickLoginWaitSeconds(int val) { - setAttribute("minimumQuickLoginWaitSeconds", val); - } - - @Override - public int getMaxDeltaTimeSeconds() { - return getAttribute("maxDeltaTimeSeconds", 0); - } - - @Override - public void setMaxDeltaTimeSeconds(int val) { - setAttribute("maxDeltaTimeSeconds", val); - } - - @Override - public int getFailureFactor() { - return getAttribute("failureFactor", 0); - } - - @Override - public void setFailureFactor(int failureFactor) { - setAttribute("failureFactor", failureFactor); - } - - @Override - public boolean isVerifyEmail() { - return realm.isVerifyEmail(); - } - - @Override - public void setVerifyEmail(boolean verifyEmail) { - realm.setVerifyEmail(verifyEmail); - em.flush(); - } - - @Override - public boolean isResetPasswordAllowed() { - return realm.isResetPasswordAllowed(); - } - - @Override - public void setResetPasswordAllowed(boolean resetPasswordAllowed) { - realm.setResetPasswordAllowed(resetPasswordAllowed); - em.flush(); - } - - @Override - public int getNotBefore() { - return realm.getNotBefore(); - } - - @Override - public void setNotBefore(int notBefore) { - realm.setNotBefore(notBefore); - } - - @Override - public int getAccessTokenLifespan() { - return realm.getAccessTokenLifespan(); - } - - @Override - public void setAccessTokenLifespan(int tokenLifespan) { - realm.setAccessTokenLifespan(tokenLifespan); - em.flush(); - } - - @Override - public int getSsoSessionIdleTimeout() { - return realm.getSsoSessionIdleTimeout(); - } - - @Override - public void setSsoSessionIdleTimeout(int seconds) { - realm.setSsoSessionIdleTimeout(seconds); - } - - @Override - public int getSsoSessionMaxLifespan() { - return realm.getSsoSessionMaxLifespan(); - } - - @Override - public void setSsoSessionMaxLifespan(int seconds) { - realm.setSsoSessionMaxLifespan(seconds); - } - - @Override - public int getAccessCodeLifespan() { - return realm.getAccessCodeLifespan(); - } - - @Override - public void setAccessCodeLifespan(int accessCodeLifespan) { - realm.setAccessCodeLifespan(accessCodeLifespan); - em.flush(); - } - - @Override - public int getAccessCodeLifespanUserAction() { - return realm.getAccessCodeLifespanUserAction(); - } - - @Override - public void setAccessCodeLifespanUserAction(int accessCodeLifespanUserAction) { - realm.setAccessCodeLifespanUserAction(accessCodeLifespanUserAction); - em.flush(); - } - - @Override - public int getAccessCodeLifespanLogin() { - return realm.getAccessCodeLifespanLogin(); - } - - @Override - public void setAccessCodeLifespanLogin(int accessCodeLifespanLogin) { - realm.setAccessCodeLifespanLogin(accessCodeLifespanLogin); - em.flush(); - } - - @Override - public String getPublicKeyPem() { - return realm.getPublicKeyPem(); - } - - @Override - public void setPublicKeyPem(String publicKeyPem) { - realm.setPublicKeyPem(publicKeyPem); - em.flush(); - } - - @Override - public X509Certificate getCertificate() { - if (certificate != null) return certificate; - certificate = KeycloakModelUtils.getCertificate(getCertificatePem()); - return certificate; - } - - @Override - public void setCertificate(X509Certificate certificate) { - this.certificate = certificate; - String certificatePem = KeycloakModelUtils.getPemFromCertificate(certificate); - setCertificatePem(certificatePem); - - } - - @Override - public String getCertificatePem() { - return realm.getCertificatePem(); - } - - @Override - public void setCertificatePem(String certificate) { - realm.setCertificatePem(certificate); - - } - - @Override - public String getPrivateKeyPem() { - return realm.getPrivateKeyPem(); - } - - @Override - public void setPrivateKeyPem(String privateKeyPem) { - realm.setPrivateKeyPem(privateKeyPem); - em.flush(); - } - - @Override - public PublicKey getPublicKey() { - if (publicKey != null) return publicKey; - publicKey = KeycloakModelUtils.getPublicKey(getPublicKeyPem()); - return publicKey; - } - - @Override - public void setPublicKey(PublicKey publicKey) { - this.publicKey = publicKey; - String publicKeyPem = KeycloakModelUtils.getPemFromKey(publicKey); - setPublicKeyPem(publicKeyPem); - } - - @Override - public PrivateKey getPrivateKey() { - if (privateKey != null) return privateKey; - privateKey = KeycloakModelUtils.getPrivateKey(getPrivateKeyPem()); - return privateKey; - } - - @Override - public void setPrivateKey(PrivateKey privateKey) { - this.privateKey = privateKey; - String privateKeyPem = KeycloakModelUtils.getPemFromKey(privateKey); - setPrivateKeyPem(privateKeyPem); - } - - @Override - public String getCodeSecret() { - return realm.getCodeSecret(); - } - - @Override - public Key getCodeSecretKey() { - if (codeSecretKey == null) { - codeSecretKey = KeycloakModelUtils.getSecretKey(getCodeSecret()); - } - return codeSecretKey; - } - - @Override - public void setCodeSecret(String codeSecret) { - realm.setCodeSecret(codeSecret); - } - - protected RequiredCredentialModel initRequiredCredentialModel(String type) { - RequiredCredentialModel model = RequiredCredentialModel.BUILT_IN.get(type); - if (model == null) { - throw new RuntimeException("Unknown credential type " + type); - } - return model; - } - - @Override - public void addRequiredCredential(String type) { - RequiredCredentialModel model = initRequiredCredentialModel(type); - addRequiredCredential(model); - em.flush(); - } - - public void addRequiredCredential(RequiredCredentialModel model) { - RequiredCredentialEntity entity = new RequiredCredentialEntity(); - entity.setRealm(realm); - entity.setInput(model.isInput()); - entity.setSecret(model.isSecret()); - entity.setType(model.getType()); - entity.setFormLabel(model.getFormLabel()); - em.persist(entity); - realm.getRequiredCredentials().add(entity); - em.flush(); - } - - @Override - public void updateRequiredCredentials(Set creds) { - Collection relationships = realm.getRequiredCredentials(); - if (relationships == null) relationships = new ArrayList(); - - Set already = new HashSet(); - List remove = new ArrayList(); - for (RequiredCredentialEntity rel : relationships) { - if (!creds.contains(rel.getType())) { - remove.add(rel); - } else { - already.add(rel.getType()); - } - } - for (RequiredCredentialEntity entity : remove) { - relationships.remove(entity); - em.remove(entity); - } - for (String cred : creds) { - if (!already.contains(cred)) { - addRequiredCredential(cred); - } - } - em.flush(); - } - - - @Override - public List getRequiredCredentials() { - List requiredCredentialModels = new ArrayList(); - Collection entities = realm.getRequiredCredentials(); - if (entities == null) return requiredCredentialModels; - for (RequiredCredentialEntity entity : entities) { - RequiredCredentialModel model = new RequiredCredentialModel(); - model.setFormLabel(entity.getFormLabel()); - model.setType(entity.getType()); - model.setSecret(entity.isSecret()); - model.setInput(entity.isInput()); - requiredCredentialModels.add(model); - } - return requiredCredentialModels; //To change body of implemented methods use File | Settings | File Templates. - } - - - @Override - public List getDefaultRoles() { - Collection entities = realm.getDefaultRoles(); - List roles = new ArrayList(); - if (entities == null) return roles; - for (RoleEntity entity : entities) { - roles.add(entity.getName()); - } - return roles; - } - - @Override - public void addDefaultRole(String name) { - RoleModel role = getRole(name); - if (role == null) { - role = addRole(name); - } - Collection entities = realm.getDefaultRoles(); - for (RoleEntity entity : entities) { - if (entity.getId().equals(role.getId())) { - return; - } - } - RoleEntity roleEntity = RoleAdapter.toRoleEntity(role, em); - entities.add(roleEntity); - em.flush(); - } - - public static boolean contains(String str, String[] array) { - for (String s : array) { - if (str.equals(s)) return true; - } - return false; - } - - @Override - public void updateDefaultRoles(String[] defaultRoles) { - Collection entities = realm.getDefaultRoles(); - Set already = new HashSet(); - List remove = new ArrayList(); - for (RoleEntity rel : entities) { - if (!contains(rel.getName(), defaultRoles)) { - remove.add(rel); - } else { - already.add(rel.getName()); - } - } - for (RoleEntity entity : remove) { - entities.remove(entity); - } - em.flush(); - for (String roleName : defaultRoles) { - if (!already.contains(roleName)) { - addDefaultRole(roleName); - } - } - em.flush(); - } - - @Override - public ClientModel findClient(String clientId) { - ClientModel model = getApplicationByName(clientId); - if (model != null) return model; - return getOAuthClient(clientId); - } - - @Override - public ClientModel findClientById(String id) { - ClientModel model = getApplicationById(id); - if (model != null) return model; - return getOAuthClientById(id); - } - - @Override - public Map getApplicationNameMap() { - Map map = new HashMap(); - for (ApplicationModel app : getApplications()) { - map.put(app.getName(), app); - } - return map; //To change body of implemented methods use File | Settings | File Templates. - } - - @Override - public List getApplications() { - List list = new ArrayList(); - if (realm.getApplications() == null) return list; - for (ApplicationEntity entity : realm.getApplications()) { - list.add(new ApplicationAdapter(this, em, session, entity)); - } - return list; - } - - @Override - public ApplicationModel addApplication(String name) { - return this.addApplication(KeycloakModelUtils.generateId(), name); - } - - @Override - public ApplicationModel addApplication(String id, String name) { - ApplicationEntity applicationData = new ApplicationEntity(); - applicationData.setId(id); - applicationData.setName(name); - applicationData.setEnabled(true); - applicationData.setRealm(realm); - realm.getApplications().add(applicationData); - em.persist(applicationData); - em.flush(); - final ApplicationModel resource = new ApplicationAdapter(this, em, session, applicationData); - em.flush(); - session.getKeycloakSessionFactory().publish(new ApplicationCreationEvent() { - @Override - public ApplicationModel getCreatedApplication() { - return resource; - } - - @Override - public ClientModel getCreatedClient() { - return resource; - } - }); - return resource; - } - - @Override - public boolean removeApplication(String id) { - if (id == null) return false; - ApplicationModel application = getApplicationById(id); - if (application == null) return false; - - for (RoleModel role : application.getRoles()) { - application.removeRole(role); - } - - ApplicationEntity applicationEntity = null; - Iterator it = realm.getApplications().iterator(); - while (it.hasNext()) { - ApplicationEntity ae = it.next(); - if (ae.getId().equals(id)) { - applicationEntity = ae; - it.remove(); - break; - } - } - for (ApplicationEntity a : realm.getApplications()) { - if (a.getId().equals(id)) { - applicationEntity = a; - } - } - if (application == null) { - return false; - } - em.remove(applicationEntity); - em.createNamedQuery("deleteScopeMappingByClient").setParameter("client", applicationEntity).executeUpdate(); - em.flush(); - - return true; - } - - @Override - public ApplicationModel getApplicationById(String id) { - return session.realms().getApplicationById(id, this); - } - - @Override - public ApplicationModel getApplicationByName(String name) { - return getApplicationNameMap().get(name); - } - - @Override - public OAuthClientModel addOAuthClient(String name) { - return this.addOAuthClient(KeycloakModelUtils.generateId(), name); - } - - @Override - public OAuthClientModel addOAuthClient(String id, String name) { - OAuthClientEntity data = new OAuthClientEntity(); - data.setId(id); - data.setEnabled(true); - data.setName(name); - data.setRealm(realm); - em.persist(data); - em.flush(); - final OAuthClientModel model = new OAuthClientAdapter(this, data, em); - em.flush(); - session.getKeycloakSessionFactory().publish(new OAuthClientCreationEvent() { - @Override - public OAuthClientModel getCreatedOAuthClient() { - return model; - } - - @Override - public ClientModel getCreatedClient() { - return model; - } - }); - return model; - } - - @Override - public boolean removeOAuthClient(String id) { - OAuthClientModel oauth = getOAuthClientById(id); - if (oauth == null) return false; - OAuthClientEntity client = em.getReference(OAuthClientEntity.class, oauth.getId()); - em.createNamedQuery("deleteScopeMappingByClient").setParameter("client", client).executeUpdate(); - em.remove(client); - return true; - } - - - @Override - public OAuthClientModel getOAuthClient(String name) { - TypedQuery query = em.createNamedQuery("findOAuthClientByName", OAuthClientEntity.class); - query.setParameter("name", name); - query.setParameter("realm", realm); - List entities = query.getResultList(); - if (entities.size() == 0) return null; - return new OAuthClientAdapter(this, entities.get(0), em); - } - - @Override - public OAuthClientModel getOAuthClientById(String id) { - return session.realms().getOAuthClientById(id, this); - } - - - @Override - public List getOAuthClients() { - TypedQuery query = em.createNamedQuery("findOAuthClientByRealm", OAuthClientEntity.class); - query.setParameter("realm", realm); - List entities = query.getResultList(); - List list = new ArrayList(); - for (OAuthClientEntity entity : entities) list.add(new OAuthClientAdapter(this, entity, em)); - return list; - } - - private static final String BROWSER_HEADER_PREFIX = "_browser_header."; - - @Override - public Map getBrowserSecurityHeaders() { - Map attributes = getAttributes(); - Map headers = new HashMap(); - for (Map.Entry entry : attributes.entrySet()) { - if (entry.getKey().startsWith(BROWSER_HEADER_PREFIX)) { - headers.put(entry.getKey().substring(BROWSER_HEADER_PREFIX.length()), entry.getValue()); - } - } - return headers; - } - - @Override - public void setBrowserSecurityHeaders(Map headers) { - for (Map.Entry entry : headers.entrySet()) { - setAttribute(BROWSER_HEADER_PREFIX + entry.getKey(), entry.getValue()); - } - } - - @Override - public Map getSmtpConfig() { - return realm.getSmtpConfig(); - } - - @Override - public void setSmtpConfig(Map smtpConfig) { - realm.setSmtpConfig(smtpConfig); - em.flush(); - } - - @Override - public List getUserFederationProviders() { - List entities = realm.getUserFederationProviders(); - List copy = new ArrayList(); - for (UserFederationProviderEntity entity : entities) { - copy.add(entity); - - } - Collections.sort(copy, new Comparator() { - - @Override - public int compare(UserFederationProviderEntity o1, UserFederationProviderEntity o2) { - return o1.getPriority() - o2.getPriority(); - } - - }); - List result = new ArrayList(); - for (UserFederationProviderEntity entity : copy) { - result.add(new UserFederationProviderModel(entity.getId(), entity.getProviderName(), entity.getConfig(), entity.getPriority(), entity.getDisplayName(), - entity.getFullSyncPeriod(), entity.getChangedSyncPeriod(), entity.getLastSync())); - } - - return result; - } - - @Override - public UserFederationProviderModel addUserFederationProvider(String providerName, Map config, int priority, String displayName, int fullSyncPeriod, int changedSyncPeriod, int lastSync) { - String id = KeycloakModelUtils.generateId(); - UserFederationProviderEntity entity = new UserFederationProviderEntity(); - entity.setId(id); - entity.setRealm(realm); - entity.setProviderName(providerName); - entity.setConfig(config); - entity.setPriority(priority); - if (displayName == null) { - displayName = id; - } - entity.setDisplayName(displayName); - entity.setFullSyncPeriod(fullSyncPeriod); - entity.setChangedSyncPeriod(changedSyncPeriod); - entity.setLastSync(lastSync); - em.persist(entity); - realm.getUserFederationProviders().add(entity); - em.flush(); - return new UserFederationProviderModel(entity.getId(), providerName, config, priority, displayName, fullSyncPeriod, changedSyncPeriod, lastSync); - } - - @Override - public void removeUserFederationProvider(UserFederationProviderModel provider) { - Iterator it = realm.getUserFederationProviders().iterator(); - while (it.hasNext()) { - UserFederationProviderEntity entity = it.next(); - if (entity.getId().equals(provider.getId())) { - session.users().preRemove(this, provider); - it.remove(); - em.remove(entity); - return; - } - } - } - @Override - public void updateUserFederationProvider(UserFederationProviderModel model) { - Iterator it = realm.getUserFederationProviders().iterator(); - while (it.hasNext()) { - UserFederationProviderEntity entity = it.next(); - if (entity.getId().equals(model.getId())) { - String displayName = model.getDisplayName(); - if (displayName != null) { - entity.setDisplayName(model.getDisplayName()); - } - entity.setConfig(model.getConfig()); - entity.setPriority(model.getPriority()); - entity.setProviderName(model.getProviderName()); - entity.setPriority(model.getPriority()); - entity.setFullSyncPeriod(model.getFullSyncPeriod()); - entity.setChangedSyncPeriod(model.getChangedSyncPeriod()); - entity.setLastSync(model.getLastSync()); - break; - } - } - } - - @Override - public void setUserFederationProviders(List providers) { - - Iterator it = realm.getUserFederationProviders().iterator(); - while (it.hasNext()) { - UserFederationProviderEntity entity = it.next(); - boolean found = false; - for (UserFederationProviderModel model : providers) { - if (entity.getId().equals(model.getId())) { - entity.setConfig(model.getConfig()); - entity.setPriority(model.getPriority()); - entity.setProviderName(model.getProviderName()); - entity.setPriority(model.getPriority()); - String displayName = model.getDisplayName(); - if (displayName != null) { - entity.setDisplayName(model.getDisplayName()); - } - entity.setFullSyncPeriod(model.getFullSyncPeriod()); - entity.setChangedSyncPeriod(model.getChangedSyncPeriod()); - entity.setLastSync(model.getLastSync()); - found = true; - break; - } - - } - if (found) continue; - session.users().preRemove(this, new UserFederationProviderModel(entity.getId(), entity.getProviderName(), entity.getConfig(), entity.getPriority(), entity.getDisplayName(), - entity.getFullSyncPeriod(), entity.getChangedSyncPeriod(), entity.getLastSync())); - it.remove(); - em.remove(entity); - } - - List add = new LinkedList(); - for (UserFederationProviderModel model : providers) { - boolean found = false; - for (UserFederationProviderEntity entity : realm.getUserFederationProviders()) { - if (entity.getId().equals(model.getId())) { - found = true; - break; - } - } - if (!found) add.add(model); - } - - for (UserFederationProviderModel model : add) { - UserFederationProviderEntity entity = new UserFederationProviderEntity(); - if (model.getId() != null) entity.setId(model.getId()); - else entity.setId(KeycloakModelUtils.generateId()); - entity.setConfig(model.getConfig()); - entity.setPriority(model.getPriority()); - entity.setProviderName(model.getProviderName()); - entity.setPriority(model.getPriority()); - String displayName = model.getDisplayName(); - if (displayName == null) { - displayName = entity.getId(); - } - entity.setDisplayName(displayName); - entity.setFullSyncPeriod(model.getFullSyncPeriod()); - entity.setChangedSyncPeriod(model.getChangedSyncPeriod()); - entity.setLastSync(model.getLastSync()); - em.persist(entity); - realm.getUserFederationProviders().add(entity); - - } - } - - @Override - public RoleModel getRole(String name) { - TypedQuery query = em.createNamedQuery("getRealmRoleByName", RoleEntity.class); - query.setParameter("name", name); - query.setParameter("realm", realm); - List roles = query.getResultList(); - if (roles.size() == 0) return null; - return new RoleAdapter(this, em, roles.get(0)); - } - - @Override - public RoleModel addRole(String name) { - return this.addRole(KeycloakModelUtils.generateId(), name); - } - - @Override - public RoleModel addRole(String id, String name) { - RoleEntity entity = new RoleEntity(); - entity.setId(id); - entity.setName(name); - entity.setRealm(realm); - entity.setRealmId(realm.getId()); - realm.getRoles().add(entity); - em.persist(entity); - em.flush(); - return new RoleAdapter(this, em, entity); - } - - @Override - public boolean removeRole(RoleModel role) { - if (role == null) { - return false; - } - if (!role.getContainer().equals(this)) return false; - session.users().preRemove(this, role); - RoleEntity roleEntity = RoleAdapter.toRoleEntity(role, em); - realm.getRoles().remove(roleEntity); - realm.getDefaultRoles().remove(roleEntity); - - em.createNativeQuery("delete from COMPOSITE_ROLE where CHILD_ROLE = :role").setParameter("role", roleEntity).executeUpdate(); - em.createNamedQuery("deleteScopeMappingByRole").setParameter("role", roleEntity).executeUpdate(); - - em.remove(roleEntity); - - return true; - } - - @Override - public Set getRoles() { - Set list = new HashSet(); - Collection roles = realm.getRoles(); - if (roles == null) return list; - for (RoleEntity entity : roles) { - list.add(new RoleAdapter(this, em, entity)); - } - return list; - } - - @Override - public RoleModel getRoleById(String id) { - return session.realms().getRoleById(id, this); - } - - @Override - public boolean removeRoleById(String id) { - RoleModel role = getRoleById(id); - if (role == null) return false; - return role.getContainer().removeRole(role); - } - - @Override - public PasswordPolicy getPasswordPolicy() { - if (passwordPolicy == null) { - passwordPolicy = new PasswordPolicy(realm.getPasswordPolicy()); - } - return passwordPolicy; - } - - @Override - public void setPasswordPolicy(PasswordPolicy policy) { - this.passwordPolicy = policy; - realm.setPasswordPolicy(policy.toString()); - em.flush(); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || !(o instanceof RealmModel)) return false; - - RealmModel that = (RealmModel) o; - return that.getId().equals(getId()); - } - - @Override - public int hashCode() { - return getId().hashCode(); - } - - @Override - public String getLoginTheme() { - return realm.getLoginTheme(); - } - - @Override - public void setLoginTheme(String name) { - realm.setLoginTheme(name); - em.flush(); - } - - @Override - public String getAccountTheme() { - return realm.getAccountTheme(); - } - - @Override - public void setAccountTheme(String name) { - realm.setAccountTheme(name); - em.flush(); - } - - @Override - public String getAdminTheme() { - return realm.getAdminTheme(); - } - - @Override - public void setAdminTheme(String name) { - realm.setAdminTheme(name); - em.flush(); - } - - @Override - public String getEmailTheme() { - return realm.getEmailTheme(); - } - - @Override - public void setEmailTheme(String name) { - realm.setEmailTheme(name); - em.flush(); - } - - @Override - public boolean isEventsEnabled() { - return realm.isEventsEnabled(); - } - - @Override - public void setEventsEnabled(boolean enabled) { - realm.setEventsEnabled(enabled); - em.flush(); - } - - @Override - public long getEventsExpiration() { - return realm.getEventsExpiration(); - } - - @Override - public void setEventsExpiration(long expiration) { - realm.setEventsExpiration(expiration); - em.flush(); - } - - @Override - public Set getEventsListeners() { - return realm.getEventsListeners(); - } - - @Override - public void setEventsListeners(Set listeners) { - realm.setEventsListeners(listeners); - em.flush(); - } - - @Override - public Set getEnabledEventTypes() { - return realm.getEnabledEventTypes(); - } - - @Override - public void setEnabledEventTypes(Set enabledEventTypes) { - realm.setEnabledEventTypes(enabledEventTypes); - em.flush(); - } - - @Override - public ApplicationModel getMasterAdminApp() { - return new ApplicationAdapter(this, em, session, realm.getMasterAdminApp()); - } - - @Override - public void setMasterAdminApp(ApplicationModel app) { - ApplicationEntity appEntity = app!=null ? em.getReference(ApplicationEntity.class, app.getId()) : null; - realm.setMasterAdminApp(appEntity); - em.flush(); - } - - @Override - public List getIdentityProviders() { - List identityProviders = new ArrayList(); - - for (IdentityProviderEntity entity: realm.getIdentityProviders()) { - IdentityProviderModel identityProviderModel = new IdentityProviderModel(); - - identityProviderModel.setProviderId(entity.getProviderId()); - identityProviderModel.setAlias(entity.getAlias()); - identityProviderModel.setInternalId(entity.getInternalId()); - identityProviderModel.setConfig(entity.getConfig()); - identityProviderModel.setEnabled(entity.isEnabled()); - identityProviderModel.setUpdateProfileFirstLogin(entity.isUpdateProfileFirstLogin()); - identityProviderModel.setAuthenticateByDefault(entity.isAuthenticateByDefault()); - identityProviderModel.setStoreToken(entity.isStoreToken()); - - identityProviders.add(identityProviderModel); - } - - return identityProviders; - } - - @Override - public IdentityProviderModel getIdentityProviderByAlias(String alias) { - for (IdentityProviderModel identityProviderModel : getIdentityProviders()) { - if (identityProviderModel.getAlias().equals(alias)) { - return identityProviderModel; - } - } - - return null; - } - - @Override - public void addIdentityProvider(IdentityProviderModel identityProvider) { - IdentityProviderEntity entity = new IdentityProviderEntity(); - - entity.setInternalId(KeycloakModelUtils.generateId()); - entity.setAlias(identityProvider.getAlias()); - entity.setProviderId(identityProvider.getProviderId()); - entity.setEnabled(identityProvider.isEnabled()); - entity.setStoreToken(identityProvider.isStoreToken()); - entity.setUpdateProfileFirstLogin(identityProvider.isUpdateProfileFirstLogin()); - entity.setAuthenticateByDefault(identityProvider.isAuthenticateByDefault()); - entity.setConfig(identityProvider.getConfig()); - - realm.addIdentityProvider(entity); - - em.persist(entity); - em.flush(); - } - - @Override - public void removeIdentityProviderByAlias(String alias) { - for (IdentityProviderEntity entity : realm.getIdentityProviders()) { - if (entity.getAlias().equals(alias)) { - em.remove(entity); - em.flush(); - } - } - } - - @Override - public void updateIdentityProvider(IdentityProviderModel identityProvider) { - for (IdentityProviderEntity entity : this.realm.getIdentityProviders()) { - if (entity.getInternalId().equals(identityProvider.getInternalId())) { - entity.setAlias(identityProvider.getAlias()); - entity.setEnabled(identityProvider.isEnabled()); - entity.setUpdateProfileFirstLogin(identityProvider.isUpdateProfileFirstLogin()); - entity.setAuthenticateByDefault(identityProvider.isAuthenticateByDefault()); - entity.setStoreToken(identityProvider.isStoreToken()); - entity.setConfig(identityProvider.getConfig()); - } - } - - em.flush(); - } - - @Override - public boolean isIdentityFederationEnabled() { - return !this.realm.getIdentityProviders().isEmpty(); - } - - @Override - public boolean isInternationalizationEnabled() { - return realm.isInternationalizationEnabled(); - } - - @Override - public void setInternationalizationEnabled(boolean enabled) { - realm.setInternationalizationEnabled(enabled); - em.flush(); - } - - @Override - public Set getSupportedLocales() { - return realm.getSupportedLocales(); - } - - @Override - public void setSupportedLocales(Set locales) { - realm.setSupportedLocales(locales); - em.flush(); - } - - @Override - public String getDefaultLocale() { - return realm.getDefaultLocale(); - } - - @Override - public void setDefaultLocale(String locale) { - realm.setDefaultLocale(locale); - em.flush(); - } - - @Override - public Set getIdentityProviderMappers() { - Set mappings = new HashSet(); - for (IdentityProviderMapperEntity entity : this.realm.getIdentityProviderMappers()) { - IdentityProviderMapperModel mapping = new IdentityProviderMapperModel(); - mapping.setId(entity.getId()); - mapping.setName(entity.getName()); - mapping.setIdentityProviderAlias(entity.getIdentityProviderAlias()); - mapping.setIdentityProviderMapper(entity.getIdentityProviderMapper()); - Map config = new HashMap(); - if (entity.getConfig() != null) { - config.putAll(entity.getConfig()); - } - mapping.setConfig(config); - mappings.add(mapping); - } - return mappings; - } - - @Override - public Set getIdentityProviderMappersByAlias(String brokerAlias) { - Set mappings = new HashSet(); - for (IdentityProviderMapperEntity entity : this.realm.getIdentityProviderMappers()) { - if (!entity.getIdentityProviderAlias().equals(brokerAlias)) { - continue; - } - IdentityProviderMapperModel mapping = new IdentityProviderMapperModel(); - mapping.setId(entity.getId()); - mapping.setName(entity.getName()); - mapping.setIdentityProviderAlias(entity.getIdentityProviderAlias()); - mapping.setIdentityProviderMapper(entity.getIdentityProviderMapper()); - Map config = new HashMap(); - if (entity.getConfig() != null) { - config.putAll(entity.getConfig()); - } - mapping.setConfig(config); - mappings.add(mapping); - } - return mappings; - } - - @Override - public IdentityProviderMapperModel addIdentityProviderMapper(IdentityProviderMapperModel model) { - if (getIdentityProviderMapperByName(model.getIdentityProviderAlias(), model.getIdentityProviderMapper()) != null) { - throw new RuntimeException("protocol mapper name must be unique per protocol"); - } - String id = KeycloakModelUtils.generateId(); - IdentityProviderMapperEntity entity = new IdentityProviderMapperEntity(); - entity.setId(id); - entity.setName(model.getName()); - entity.setIdentityProviderAlias(model.getIdentityProviderAlias()); - entity.setIdentityProviderMapper(model.getIdentityProviderMapper()); - entity.setRealm(this.realm); - entity.setConfig(model.getConfig()); - - em.persist(entity); - this.realm.getIdentityProviderMappers().add(entity); - return entityToModel(entity); - } - - protected IdentityProviderMapperEntity getIdentityProviderMapperEntity(String id) { - for (IdentityProviderMapperEntity entity : this.realm.getIdentityProviderMappers()) { - if (entity.getId().equals(id)) { - return entity; - } - } - return null; - - } - - protected IdentityProviderMapperEntity getIdentityProviderMapperEntityByName(String alias, String name) { - for (IdentityProviderMapperEntity entity : this.realm.getIdentityProviderMappers()) { - if (entity.getIdentityProviderAlias().equals(alias) && entity.getName().equals(name)) { - return entity; - } - } - return null; - - } - - @Override - public void removeIdentityProviderMapper(IdentityProviderMapperModel mapping) { - IdentityProviderMapperEntity toDelete = getIdentityProviderMapperEntity(mapping.getId()); - if (toDelete != null) { - this.realm.getIdentityProviderMappers().remove(toDelete); - em.remove(toDelete); - } - - } - - @Override - public void updateIdentityProviderMapper(IdentityProviderMapperModel mapping) { - IdentityProviderMapperEntity entity = getIdentityProviderMapperEntity(mapping.getId()); - entity.setIdentityProviderAlias(mapping.getIdentityProviderAlias()); - entity.setIdentityProviderMapper(mapping.getIdentityProviderMapper()); - if (entity.getConfig() == null) { - entity.setConfig(mapping.getConfig()); - } else { - entity.getConfig().clear(); - entity.getConfig().putAll(mapping.getConfig()); - } - em.flush(); - - } - - @Override - public IdentityProviderMapperModel getIdentityProviderMapperById(String id) { - IdentityProviderMapperEntity entity = getIdentityProviderMapperEntity(id); - if (entity == null) return null; - return entityToModel(entity); - } - - @Override - public IdentityProviderMapperModel getIdentityProviderMapperByName(String alias, String name) { - IdentityProviderMapperEntity entity = getIdentityProviderMapperEntityByName(alias, name); - if (entity == null) return null; - return entityToModel(entity); - } - - protected IdentityProviderMapperModel entityToModel(IdentityProviderMapperEntity entity) { - IdentityProviderMapperModel mapping = new IdentityProviderMapperModel(); - mapping.setId(entity.getId()); - mapping.setName(entity.getName()); - mapping.setIdentityProviderAlias(entity.getIdentityProviderAlias()); - mapping.setIdentityProviderMapper(entity.getIdentityProviderMapper()); - Map config = new HashMap(); - if (entity.getConfig() != null) config.putAll(entity.getConfig()); - mapping.setConfig(config); - return mapping; - } +package org.keycloak.models.jpa; + +import org.keycloak.enums.SslRequired; +import org.keycloak.models.ClientModel; +import org.keycloak.models.IdentityProviderMapperModel; +import org.keycloak.models.IdentityProviderModel; +import org.keycloak.models.KeycloakSession; +import org.keycloak.models.PasswordPolicy; +import org.keycloak.models.RealmModel; +import org.keycloak.models.RequiredCredentialModel; +import org.keycloak.models.RoleModel; +import org.keycloak.models.UserFederationProviderModel; +import org.keycloak.models.jpa.entities.ClientEntity; +import org.keycloak.models.jpa.entities.IdentityProviderEntity; +import org.keycloak.models.jpa.entities.IdentityProviderMapperEntity; +import org.keycloak.models.jpa.entities.RealmAttributeEntity; +import org.keycloak.models.jpa.entities.RealmEntity; +import org.keycloak.models.jpa.entities.RequiredCredentialEntity; +import org.keycloak.models.jpa.entities.RoleEntity; +import org.keycloak.models.jpa.entities.UserFederationProviderEntity; +import org.keycloak.models.utils.KeycloakModelUtils; + +import javax.persistence.EntityManager; +import javax.persistence.TypedQuery; +import java.security.Key; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * @author Bill Burke + * @version $Revision: 1 $ + */ +public class RealmAdapter implements RealmModel { + protected RealmEntity realm; + protected EntityManager em; + protected volatile transient PublicKey publicKey; + protected volatile transient PrivateKey privateKey; + protected volatile transient X509Certificate certificate; + protected volatile transient Key codeSecretKey; + protected KeycloakSession session; + private PasswordPolicy passwordPolicy; + + public RealmAdapter(KeycloakSession session, EntityManager em, RealmEntity realm) { + this.session = session; + this.em = em; + this.realm = realm; + } + + public RealmEntity getEntity() { + return realm; + } + + @Override + public String getId() { + return realm.getId(); + } + + @Override + public String getName() { + return realm.getName(); + } + + @Override + public void setName(String name) { + realm.setName(name); + em.flush(); + } + + @Override + public boolean isEnabled() { + return realm.isEnabled(); + } + + @Override + public void setEnabled(boolean enabled) { + realm.setEnabled(enabled); + em.flush(); + } + + @Override + public SslRequired getSslRequired() { + return realm.getSslRequired() != null ? SslRequired.valueOf(realm.getSslRequired()) : null; + } + + @Override + public void setSslRequired(SslRequired sslRequired) { + realm.setSslRequired(sslRequired.name()); + em.flush(); + } + + @Override + public boolean isPasswordCredentialGrantAllowed() { + return realm.isPasswordCredentialGrantAllowed(); + } + + @Override + public void setPasswordCredentialGrantAllowed(boolean passwordCredentialGrantAllowed) { + realm.setPasswordCredentialGrantAllowed(passwordCredentialGrantAllowed); + em.flush(); + } + + @Override + public boolean isRegistrationAllowed() { + return realm.isRegistrationAllowed(); + } + + @Override + public void setRegistrationAllowed(boolean registrationAllowed) { + realm.setRegistrationAllowed(registrationAllowed); + em.flush(); + } + + @Override + public boolean isRegistrationEmailAsUsername() { + return realm.isRegistrationEmailAsUsername(); + } + + @Override + public void setRegistrationEmailAsUsername(boolean registrationEmailAsUsername) { + realm.setRegistrationEmailAsUsername(registrationEmailAsUsername); + em.flush(); + } + + @Override + public boolean isRememberMe() { + return realm.isRememberMe(); + } + + @Override + public void setRememberMe(boolean rememberMe) { + realm.setRememberMe(rememberMe); + em.flush(); + } + + public void setAttribute(String name, String value) { + for (RealmAttributeEntity attr : realm.getAttributes()) { + if (attr.getName().equals(name)) { + attr.setValue(value); + return; + } + } + RealmAttributeEntity attr = new RealmAttributeEntity(); + attr.setName(name); + attr.setValue(value); + attr.setRealm(realm); + em.persist(attr); + realm.getAttributes().add(attr); + } + + public void setAttribute(String name, Boolean value) { + setAttribute(name, value.toString()); + } + + public void setAttribute(String name, Integer value) { + setAttribute(name, value.toString()); + } + + public void setAttribute(String name, Long value) { + setAttribute(name, value.toString()); + } + + public void removeAttribute(String name) { + Iterator it = realm.getAttributes().iterator(); + while (it.hasNext()) { + RealmAttributeEntity attr = it.next(); + if (attr.getName().equals(name)) { + it.remove(); + em.remove(attr); + } + } + } + + public String getAttribute(String name) { + for (RealmAttributeEntity attr : realm.getAttributes()) { + if (attr.getName().equals(name)) { + return attr.getValue(); + } + } + return null; + } + + public Integer getAttribute(String name, Integer defaultValue) { + String v = getAttribute(name); + return v != null ? Integer.parseInt(v) : defaultValue; + + } + + public Long getAttribute(String name, Long defaultValue) { + String v = getAttribute(name); + return v != null ? Long.parseLong(v) : defaultValue; + + } + + public Boolean getAttribute(String name, Boolean defaultValue) { + String v = getAttribute(name); + return v != null ? Boolean.parseBoolean(v) : defaultValue; + + } + + public Map getAttributes() { + // should always return a copy + Map result = new HashMap(); + for (RealmAttributeEntity attr : realm.getAttributes()) { + result.put(attr.getName(), attr.getValue()); + } + return result; + } + @Override + public boolean isBruteForceProtected() { + return getAttribute("bruteForceProtected", false); + } + + @Override + public void setBruteForceProtected(boolean value) { + setAttribute("bruteForceProtected", value); + } + + @Override + public int getMaxFailureWaitSeconds() { + return getAttribute("maxFailureWaitSeconds", 0); + } + + @Override + public void setMaxFailureWaitSeconds(int val) { + setAttribute("maxFailureWaitSeconds", val); + } + + @Override + public int getWaitIncrementSeconds() { + return getAttribute("waitIncrementSeconds", 0); + } + + @Override + public void setWaitIncrementSeconds(int val) { + setAttribute("waitIncrementSeconds", val); + } + + @Override + public long getQuickLoginCheckMilliSeconds() { + return getAttribute("quickLoginCheckMilliSeconds", 0l); + } + + @Override + public void setQuickLoginCheckMilliSeconds(long val) { + setAttribute("quickLoginCheckMilliSeconds", val); + } + + @Override + public int getMinimumQuickLoginWaitSeconds() { + return getAttribute("minimumQuickLoginWaitSeconds", 0); + } + + @Override + public void setMinimumQuickLoginWaitSeconds(int val) { + setAttribute("minimumQuickLoginWaitSeconds", val); + } + + @Override + public int getMaxDeltaTimeSeconds() { + return getAttribute("maxDeltaTimeSeconds", 0); + } + + @Override + public void setMaxDeltaTimeSeconds(int val) { + setAttribute("maxDeltaTimeSeconds", val); + } + + @Override + public int getFailureFactor() { + return getAttribute("failureFactor", 0); + } + + @Override + public void setFailureFactor(int failureFactor) { + setAttribute("failureFactor", failureFactor); + } + + @Override + public boolean isVerifyEmail() { + return realm.isVerifyEmail(); + } + + @Override + public void setVerifyEmail(boolean verifyEmail) { + realm.setVerifyEmail(verifyEmail); + em.flush(); + } + + @Override + public boolean isResetPasswordAllowed() { + return realm.isResetPasswordAllowed(); + } + + @Override + public void setResetPasswordAllowed(boolean resetPasswordAllowed) { + realm.setResetPasswordAllowed(resetPasswordAllowed); + em.flush(); + } + + @Override + public int getNotBefore() { + return realm.getNotBefore(); + } + + @Override + public void setNotBefore(int notBefore) { + realm.setNotBefore(notBefore); + } + + @Override + public int getAccessTokenLifespan() { + return realm.getAccessTokenLifespan(); + } + + @Override + public void setAccessTokenLifespan(int tokenLifespan) { + realm.setAccessTokenLifespan(tokenLifespan); + em.flush(); + } + + @Override + public int getSsoSessionIdleTimeout() { + return realm.getSsoSessionIdleTimeout(); + } + + @Override + public void setSsoSessionIdleTimeout(int seconds) { + realm.setSsoSessionIdleTimeout(seconds); + } + + @Override + public int getSsoSessionMaxLifespan() { + return realm.getSsoSessionMaxLifespan(); + } + + @Override + public void setSsoSessionMaxLifespan(int seconds) { + realm.setSsoSessionMaxLifespan(seconds); + } + + @Override + public int getAccessCodeLifespan() { + return realm.getAccessCodeLifespan(); + } + + @Override + public void setAccessCodeLifespan(int accessCodeLifespan) { + realm.setAccessCodeLifespan(accessCodeLifespan); + em.flush(); + } + + @Override + public int getAccessCodeLifespanUserAction() { + return realm.getAccessCodeLifespanUserAction(); + } + + @Override + public void setAccessCodeLifespanUserAction(int accessCodeLifespanUserAction) { + realm.setAccessCodeLifespanUserAction(accessCodeLifespanUserAction); + em.flush(); + } + + @Override + public int getAccessCodeLifespanLogin() { + return realm.getAccessCodeLifespanLogin(); + } + + @Override + public void setAccessCodeLifespanLogin(int accessCodeLifespanLogin) { + realm.setAccessCodeLifespanLogin(accessCodeLifespanLogin); + em.flush(); + } + + @Override + public String getPublicKeyPem() { + return realm.getPublicKeyPem(); + } + + @Override + public void setPublicKeyPem(String publicKeyPem) { + realm.setPublicKeyPem(publicKeyPem); + em.flush(); + } + + @Override + public X509Certificate getCertificate() { + if (certificate != null) return certificate; + certificate = KeycloakModelUtils.getCertificate(getCertificatePem()); + return certificate; + } + + @Override + public void setCertificate(X509Certificate certificate) { + this.certificate = certificate; + String certificatePem = KeycloakModelUtils.getPemFromCertificate(certificate); + setCertificatePem(certificatePem); + + } + + @Override + public String getCertificatePem() { + return realm.getCertificatePem(); + } + + @Override + public void setCertificatePem(String certificate) { + realm.setCertificatePem(certificate); + + } + + @Override + public String getPrivateKeyPem() { + return realm.getPrivateKeyPem(); + } + + @Override + public void setPrivateKeyPem(String privateKeyPem) { + realm.setPrivateKeyPem(privateKeyPem); + em.flush(); + } + + @Override + public PublicKey getPublicKey() { + if (publicKey != null) return publicKey; + publicKey = KeycloakModelUtils.getPublicKey(getPublicKeyPem()); + return publicKey; + } + + @Override + public void setPublicKey(PublicKey publicKey) { + this.publicKey = publicKey; + String publicKeyPem = KeycloakModelUtils.getPemFromKey(publicKey); + setPublicKeyPem(publicKeyPem); + } + + @Override + public PrivateKey getPrivateKey() { + if (privateKey != null) return privateKey; + privateKey = KeycloakModelUtils.getPrivateKey(getPrivateKeyPem()); + return privateKey; + } + + @Override + public void setPrivateKey(PrivateKey privateKey) { + this.privateKey = privateKey; + String privateKeyPem = KeycloakModelUtils.getPemFromKey(privateKey); + setPrivateKeyPem(privateKeyPem); + } + + @Override + public String getCodeSecret() { + return realm.getCodeSecret(); + } + + @Override + public Key getCodeSecretKey() { + if (codeSecretKey == null) { + codeSecretKey = KeycloakModelUtils.getSecretKey(getCodeSecret()); + } + return codeSecretKey; + } + + @Override + public void setCodeSecret(String codeSecret) { + realm.setCodeSecret(codeSecret); + } + + protected RequiredCredentialModel initRequiredCredentialModel(String type) { + RequiredCredentialModel model = RequiredCredentialModel.BUILT_IN.get(type); + if (model == null) { + throw new RuntimeException("Unknown credential type " + type); + } + return model; + } + + @Override + public void addRequiredCredential(String type) { + RequiredCredentialModel model = initRequiredCredentialModel(type); + addRequiredCredential(model); + em.flush(); + } + + public void addRequiredCredential(RequiredCredentialModel model) { + RequiredCredentialEntity entity = new RequiredCredentialEntity(); + entity.setRealm(realm); + entity.setInput(model.isInput()); + entity.setSecret(model.isSecret()); + entity.setType(model.getType()); + entity.setFormLabel(model.getFormLabel()); + em.persist(entity); + realm.getRequiredCredentials().add(entity); + em.flush(); + } + + @Override + public void updateRequiredCredentials(Set creds) { + Collection relationships = realm.getRequiredCredentials(); + if (relationships == null) relationships = new ArrayList(); + + Set already = new HashSet(); + List remove = new ArrayList(); + for (RequiredCredentialEntity rel : relationships) { + if (!creds.contains(rel.getType())) { + remove.add(rel); + } else { + already.add(rel.getType()); + } + } + for (RequiredCredentialEntity entity : remove) { + relationships.remove(entity); + em.remove(entity); + } + for (String cred : creds) { + if (!already.contains(cred)) { + addRequiredCredential(cred); + } + } + em.flush(); + } + + + @Override + public List getRequiredCredentials() { + List requiredCredentialModels = new ArrayList(); + Collection entities = realm.getRequiredCredentials(); + if (entities == null) return requiredCredentialModels; + for (RequiredCredentialEntity entity : entities) { + RequiredCredentialModel model = new RequiredCredentialModel(); + model.setFormLabel(entity.getFormLabel()); + model.setType(entity.getType()); + model.setSecret(entity.isSecret()); + model.setInput(entity.isInput()); + requiredCredentialModels.add(model); + } + return requiredCredentialModels; //To change body of implemented methods use File | Settings | File Templates. + } + + + @Override + public List getDefaultRoles() { + Collection entities = realm.getDefaultRoles(); + List roles = new ArrayList(); + if (entities == null) return roles; + for (RoleEntity entity : entities) { + roles.add(entity.getName()); + } + return roles; + } + + @Override + public void addDefaultRole(String name) { + RoleModel role = getRole(name); + if (role == null) { + role = addRole(name); + } + Collection entities = realm.getDefaultRoles(); + for (RoleEntity entity : entities) { + if (entity.getId().equals(role.getId())) { + return; + } + } + RoleEntity roleEntity = RoleAdapter.toRoleEntity(role, em); + entities.add(roleEntity); + em.flush(); + } + + public static boolean contains(String str, String[] array) { + for (String s : array) { + if (str.equals(s)) return true; + } + return false; + } + + @Override + public void updateDefaultRoles(String[] defaultRoles) { + Collection entities = realm.getDefaultRoles(); + Set already = new HashSet(); + List remove = new ArrayList(); + for (RoleEntity rel : entities) { + if (!contains(rel.getName(), defaultRoles)) { + remove.add(rel); + } else { + already.add(rel.getName()); + } + } + for (RoleEntity entity : remove) { + entities.remove(entity); + } + em.flush(); + for (String roleName : defaultRoles) { + if (!already.contains(roleName)) { + addDefaultRole(roleName); + } + } + em.flush(); + } + + @Override + public Map getClientNameMap() { + Map map = new HashMap(); + for (ClientModel app : getClients()) { + map.put(app.getClientId(), app); + } + return map; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public List getClients() { + List list = new ArrayList(); + if (realm.getApplications() == null) return list; + for (ClientEntity entity : realm.getApplications()) { + list.add(new ClientAdapter(this, em, session, entity)); + } + return list; + } + + @Override + public ClientModel addClient(String name) { + return this.addClient(KeycloakModelUtils.generateId(), name); + } + + @Override + public ClientModel addClient(String id, String clientId) { + ClientEntity applicationData = new ClientEntity(); + applicationData.setId(id); + applicationData.setClientId(clientId); + applicationData.setEnabled(true); + applicationData.setRealm(realm); + realm.getApplications().add(applicationData); + em.persist(applicationData); + em.flush(); + final ClientModel resource = new ClientAdapter(this, em, session, applicationData); + em.flush(); + session.getKeycloakSessionFactory().publish(new ClientCreationEvent() { + @Override + public ClientModel getCreatedClient() { + return resource; + } + }); + return resource; + } + + @Override + public boolean removeClient(String id) { + if (id == null) return false; + ClientModel application = getClientById(id); + if (application == null) return false; + + for (RoleModel role : application.getRoles()) { + application.removeRole(role); + } + + ClientEntity clientEntity = null; + Iterator it = realm.getApplications().iterator(); + while (it.hasNext()) { + ClientEntity ae = it.next(); + if (ae.getId().equals(id)) { + clientEntity = ae; + it.remove(); + break; + } + } + for (ClientEntity a : realm.getApplications()) { + if (a.getId().equals(id)) { + clientEntity = a; + } + } + if (application == null) { + return false; + } + em.remove(clientEntity); + em.createNamedQuery("deleteScopeMappingByClient").setParameter("client", clientEntity).executeUpdate(); + em.flush(); + + return true; + } + + @Override + public ClientModel getClientById(String id) { + return session.realms().getClientById(id, this); + } + + @Override + public ClientModel getClientByClientId(String clientId) { + return getClientNameMap().get(clientId); + } + + private static final String BROWSER_HEADER_PREFIX = "_browser_header."; + + @Override + public Map getBrowserSecurityHeaders() { + Map attributes = getAttributes(); + Map headers = new HashMap(); + for (Map.Entry entry : attributes.entrySet()) { + if (entry.getKey().startsWith(BROWSER_HEADER_PREFIX)) { + headers.put(entry.getKey().substring(BROWSER_HEADER_PREFIX.length()), entry.getValue()); + } + } + return headers; + } + + @Override + public void setBrowserSecurityHeaders(Map headers) { + for (Map.Entry entry : headers.entrySet()) { + setAttribute(BROWSER_HEADER_PREFIX + entry.getKey(), entry.getValue()); + } + } + + @Override + public Map getSmtpConfig() { + return realm.getSmtpConfig(); + } + + @Override + public void setSmtpConfig(Map smtpConfig) { + realm.setSmtpConfig(smtpConfig); + em.flush(); + } + + @Override + public List getUserFederationProviders() { + List entities = realm.getUserFederationProviders(); + List copy = new ArrayList(); + for (UserFederationProviderEntity entity : entities) { + copy.add(entity); + + } + Collections.sort(copy, new Comparator() { + + @Override + public int compare(UserFederationProviderEntity o1, UserFederationProviderEntity o2) { + return o1.getPriority() - o2.getPriority(); + } + + }); + List result = new ArrayList(); + for (UserFederationProviderEntity entity : copy) { + result.add(new UserFederationProviderModel(entity.getId(), entity.getProviderName(), entity.getConfig(), entity.getPriority(), entity.getDisplayName(), + entity.getFullSyncPeriod(), entity.getChangedSyncPeriod(), entity.getLastSync())); + } + + return result; + } + + @Override + public UserFederationProviderModel addUserFederationProvider(String providerName, Map config, int priority, String displayName, int fullSyncPeriod, int changedSyncPeriod, int lastSync) { + String id = KeycloakModelUtils.generateId(); + UserFederationProviderEntity entity = new UserFederationProviderEntity(); + entity.setId(id); + entity.setRealm(realm); + entity.setProviderName(providerName); + entity.setConfig(config); + entity.setPriority(priority); + if (displayName == null) { + displayName = id; + } + entity.setDisplayName(displayName); + entity.setFullSyncPeriod(fullSyncPeriod); + entity.setChangedSyncPeriod(changedSyncPeriod); + entity.setLastSync(lastSync); + em.persist(entity); + realm.getUserFederationProviders().add(entity); + em.flush(); + return new UserFederationProviderModel(entity.getId(), providerName, config, priority, displayName, fullSyncPeriod, changedSyncPeriod, lastSync); + } + + @Override + public void removeUserFederationProvider(UserFederationProviderModel provider) { + Iterator it = realm.getUserFederationProviders().iterator(); + while (it.hasNext()) { + UserFederationProviderEntity entity = it.next(); + if (entity.getId().equals(provider.getId())) { + session.users().preRemove(this, provider); + it.remove(); + em.remove(entity); + return; + } + } + } + @Override + public void updateUserFederationProvider(UserFederationProviderModel model) { + Iterator it = realm.getUserFederationProviders().iterator(); + while (it.hasNext()) { + UserFederationProviderEntity entity = it.next(); + if (entity.getId().equals(model.getId())) { + String displayName = model.getDisplayName(); + if (displayName != null) { + entity.setDisplayName(model.getDisplayName()); + } + entity.setConfig(model.getConfig()); + entity.setPriority(model.getPriority()); + entity.setProviderName(model.getProviderName()); + entity.setPriority(model.getPriority()); + entity.setFullSyncPeriod(model.getFullSyncPeriod()); + entity.setChangedSyncPeriod(model.getChangedSyncPeriod()); + entity.setLastSync(model.getLastSync()); + break; + } + } + } + + @Override + public void setUserFederationProviders(List providers) { + + Iterator it = realm.getUserFederationProviders().iterator(); + while (it.hasNext()) { + UserFederationProviderEntity entity = it.next(); + boolean found = false; + for (UserFederationProviderModel model : providers) { + if (entity.getId().equals(model.getId())) { + entity.setConfig(model.getConfig()); + entity.setPriority(model.getPriority()); + entity.setProviderName(model.getProviderName()); + entity.setPriority(model.getPriority()); + String displayName = model.getDisplayName(); + if (displayName != null) { + entity.setDisplayName(model.getDisplayName()); + } + entity.setFullSyncPeriod(model.getFullSyncPeriod()); + entity.setChangedSyncPeriod(model.getChangedSyncPeriod()); + entity.setLastSync(model.getLastSync()); + found = true; + break; + } + + } + if (found) continue; + session.users().preRemove(this, new UserFederationProviderModel(entity.getId(), entity.getProviderName(), entity.getConfig(), entity.getPriority(), entity.getDisplayName(), + entity.getFullSyncPeriod(), entity.getChangedSyncPeriod(), entity.getLastSync())); + it.remove(); + em.remove(entity); + } + + List add = new LinkedList(); + for (UserFederationProviderModel model : providers) { + boolean found = false; + for (UserFederationProviderEntity entity : realm.getUserFederationProviders()) { + if (entity.getId().equals(model.getId())) { + found = true; + break; + } + } + if (!found) add.add(model); + } + + for (UserFederationProviderModel model : add) { + UserFederationProviderEntity entity = new UserFederationProviderEntity(); + if (model.getId() != null) entity.setId(model.getId()); + else entity.setId(KeycloakModelUtils.generateId()); + entity.setConfig(model.getConfig()); + entity.setPriority(model.getPriority()); + entity.setProviderName(model.getProviderName()); + entity.setPriority(model.getPriority()); + String displayName = model.getDisplayName(); + if (displayName == null) { + displayName = entity.getId(); + } + entity.setDisplayName(displayName); + entity.setFullSyncPeriod(model.getFullSyncPeriod()); + entity.setChangedSyncPeriod(model.getChangedSyncPeriod()); + entity.setLastSync(model.getLastSync()); + em.persist(entity); + realm.getUserFederationProviders().add(entity); + + } + } + + @Override + public RoleModel getRole(String name) { + TypedQuery query = em.createNamedQuery("getRealmRoleByName", RoleEntity.class); + query.setParameter("name", name); + query.setParameter("realm", realm); + List roles = query.getResultList(); + if (roles.size() == 0) return null; + return new RoleAdapter(this, em, roles.get(0)); + } + + @Override + public RoleModel addRole(String name) { + return this.addRole(KeycloakModelUtils.generateId(), name); + } + + @Override + public RoleModel addRole(String id, String name) { + RoleEntity entity = new RoleEntity(); + entity.setId(id); + entity.setName(name); + entity.setRealm(realm); + entity.setRealmId(realm.getId()); + realm.getRoles().add(entity); + em.persist(entity); + em.flush(); + return new RoleAdapter(this, em, entity); + } + + @Override + public boolean removeRole(RoleModel role) { + if (role == null) { + return false; + } + if (!role.getContainer().equals(this)) return false; + session.users().preRemove(this, role); + RoleEntity roleEntity = RoleAdapter.toRoleEntity(role, em); + realm.getRoles().remove(roleEntity); + realm.getDefaultRoles().remove(roleEntity); + + em.createNativeQuery("delete from COMPOSITE_ROLE where CHILD_ROLE = :role").setParameter("role", roleEntity).executeUpdate(); + em.createNamedQuery("deleteScopeMappingByRole").setParameter("role", roleEntity).executeUpdate(); + + em.remove(roleEntity); + + return true; + } + + @Override + public Set getRoles() { + Set list = new HashSet(); + Collection roles = realm.getRoles(); + if (roles == null) return list; + for (RoleEntity entity : roles) { + list.add(new RoleAdapter(this, em, entity)); + } + return list; + } + + @Override + public RoleModel getRoleById(String id) { + return session.realms().getRoleById(id, this); + } + + @Override + public boolean removeRoleById(String id) { + RoleModel role = getRoleById(id); + if (role == null) return false; + return role.getContainer().removeRole(role); + } + + @Override + public PasswordPolicy getPasswordPolicy() { + if (passwordPolicy == null) { + passwordPolicy = new PasswordPolicy(realm.getPasswordPolicy()); + } + return passwordPolicy; + } + + @Override + public void setPasswordPolicy(PasswordPolicy policy) { + this.passwordPolicy = policy; + realm.setPasswordPolicy(policy.toString()); + em.flush(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || !(o instanceof RealmModel)) return false; + + RealmModel that = (RealmModel) o; + return that.getId().equals(getId()); + } + + @Override + public int hashCode() { + return getId().hashCode(); + } + + @Override + public String getLoginTheme() { + return realm.getLoginTheme(); + } + + @Override + public void setLoginTheme(String name) { + realm.setLoginTheme(name); + em.flush(); + } + + @Override + public String getAccountTheme() { + return realm.getAccountTheme(); + } + + @Override + public void setAccountTheme(String name) { + realm.setAccountTheme(name); + em.flush(); + } + + @Override + public String getAdminTheme() { + return realm.getAdminTheme(); + } + + @Override + public void setAdminTheme(String name) { + realm.setAdminTheme(name); + em.flush(); + } + + @Override + public String getEmailTheme() { + return realm.getEmailTheme(); + } + + @Override + public void setEmailTheme(String name) { + realm.setEmailTheme(name); + em.flush(); + } + + @Override + public boolean isEventsEnabled() { + return realm.isEventsEnabled(); + } + + @Override + public void setEventsEnabled(boolean enabled) { + realm.setEventsEnabled(enabled); + em.flush(); + } + + @Override + public long getEventsExpiration() { + return realm.getEventsExpiration(); + } + + @Override + public void setEventsExpiration(long expiration) { + realm.setEventsExpiration(expiration); + em.flush(); + } + + @Override + public Set getEventsListeners() { + return realm.getEventsListeners(); + } + + @Override + public void setEventsListeners(Set listeners) { + realm.setEventsListeners(listeners); + em.flush(); + } + + @Override + public Set getEnabledEventTypes() { + return realm.getEnabledEventTypes(); + } + + @Override + public void setEnabledEventTypes(Set enabledEventTypes) { + realm.setEnabledEventTypes(enabledEventTypes); + em.flush(); + } + + @Override + public ClientModel getMasterAdminClient() { + return new ClientAdapter(this, em, session, realm.getMasterAdminApp()); + } + + @Override + public void setMasterAdminClient(ClientModel client) { + ClientEntity appEntity = client !=null ? em.getReference(ClientEntity.class, client.getId()) : null; + realm.setMasterAdminApp(appEntity); + em.flush(); + } + + @Override + public List getIdentityProviders() { + List identityProviders = new ArrayList(); + + for (IdentityProviderEntity entity: realm.getIdentityProviders()) { + IdentityProviderModel identityProviderModel = new IdentityProviderModel(); + + identityProviderModel.setProviderId(entity.getProviderId()); + identityProviderModel.setAlias(entity.getAlias()); + identityProviderModel.setInternalId(entity.getInternalId()); + identityProviderModel.setConfig(entity.getConfig()); + identityProviderModel.setEnabled(entity.isEnabled()); + identityProviderModel.setUpdateProfileFirstLogin(entity.isUpdateProfileFirstLogin()); + identityProviderModel.setAuthenticateByDefault(entity.isAuthenticateByDefault()); + identityProviderModel.setStoreToken(entity.isStoreToken()); + + identityProviders.add(identityProviderModel); + } + + return identityProviders; + } + + @Override + public IdentityProviderModel getIdentityProviderByAlias(String alias) { + for (IdentityProviderModel identityProviderModel : getIdentityProviders()) { + if (identityProviderModel.getAlias().equals(alias)) { + return identityProviderModel; + } + } + + return null; + } + + @Override + public void addIdentityProvider(IdentityProviderModel identityProvider) { + IdentityProviderEntity entity = new IdentityProviderEntity(); + + entity.setInternalId(KeycloakModelUtils.generateId()); + entity.setAlias(identityProvider.getAlias()); + entity.setProviderId(identityProvider.getProviderId()); + entity.setEnabled(identityProvider.isEnabled()); + entity.setStoreToken(identityProvider.isStoreToken()); + entity.setUpdateProfileFirstLogin(identityProvider.isUpdateProfileFirstLogin()); + entity.setAuthenticateByDefault(identityProvider.isAuthenticateByDefault()); + entity.setConfig(identityProvider.getConfig()); + + realm.addIdentityProvider(entity); + + em.persist(entity); + em.flush(); + } + + @Override + public void removeIdentityProviderByAlias(String alias) { + for (IdentityProviderEntity entity : realm.getIdentityProviders()) { + if (entity.getAlias().equals(alias)) { + em.remove(entity); + em.flush(); + } + } + } + + @Override + public void updateIdentityProvider(IdentityProviderModel identityProvider) { + for (IdentityProviderEntity entity : this.realm.getIdentityProviders()) { + if (entity.getInternalId().equals(identityProvider.getInternalId())) { + entity.setAlias(identityProvider.getAlias()); + entity.setEnabled(identityProvider.isEnabled()); + entity.setUpdateProfileFirstLogin(identityProvider.isUpdateProfileFirstLogin()); + entity.setAuthenticateByDefault(identityProvider.isAuthenticateByDefault()); + entity.setStoreToken(identityProvider.isStoreToken()); + entity.setConfig(identityProvider.getConfig()); + } + } + + em.flush(); + } + + @Override + public boolean isIdentityFederationEnabled() { + return !this.realm.getIdentityProviders().isEmpty(); + } + + @Override + public boolean isInternationalizationEnabled() { + return realm.isInternationalizationEnabled(); + } + + @Override + public void setInternationalizationEnabled(boolean enabled) { + realm.setInternationalizationEnabled(enabled); + em.flush(); + } + + @Override + public Set getSupportedLocales() { + return realm.getSupportedLocales(); + } + + @Override + public void setSupportedLocales(Set locales) { + realm.setSupportedLocales(locales); + em.flush(); + } + + @Override + public String getDefaultLocale() { + return realm.getDefaultLocale(); + } + + @Override + public void setDefaultLocale(String locale) { + realm.setDefaultLocale(locale); + em.flush(); + } + + @Override + public Set getIdentityProviderMappers() { + Set mappings = new HashSet(); + for (IdentityProviderMapperEntity entity : this.realm.getIdentityProviderMappers()) { + IdentityProviderMapperModel mapping = new IdentityProviderMapperModel(); + mapping.setId(entity.getId()); + mapping.setName(entity.getName()); + mapping.setIdentityProviderAlias(entity.getIdentityProviderAlias()); + mapping.setIdentityProviderMapper(entity.getIdentityProviderMapper()); + Map config = new HashMap(); + if (entity.getConfig() != null) { + config.putAll(entity.getConfig()); + } + mapping.setConfig(config); + mappings.add(mapping); + } + return mappings; + } + + @Override + public Set getIdentityProviderMappersByAlias(String brokerAlias) { + Set mappings = new HashSet(); + for (IdentityProviderMapperEntity entity : this.realm.getIdentityProviderMappers()) { + if (!entity.getIdentityProviderAlias().equals(brokerAlias)) { + continue; + } + IdentityProviderMapperModel mapping = new IdentityProviderMapperModel(); + mapping.setId(entity.getId()); + mapping.setName(entity.getName()); + mapping.setIdentityProviderAlias(entity.getIdentityProviderAlias()); + mapping.setIdentityProviderMapper(entity.getIdentityProviderMapper()); + Map config = new HashMap(); + if (entity.getConfig() != null) { + config.putAll(entity.getConfig()); + } + mapping.setConfig(config); + mappings.add(mapping); + } + return mappings; + } + + @Override + public IdentityProviderMapperModel addIdentityProviderMapper(IdentityProviderMapperModel model) { + if (getIdentityProviderMapperByName(model.getIdentityProviderAlias(), model.getIdentityProviderMapper()) != null) { + throw new RuntimeException("protocol mapper name must be unique per protocol"); + } + String id = KeycloakModelUtils.generateId(); + IdentityProviderMapperEntity entity = new IdentityProviderMapperEntity(); + entity.setId(id); + entity.setName(model.getName()); + entity.setIdentityProviderAlias(model.getIdentityProviderAlias()); + entity.setIdentityProviderMapper(model.getIdentityProviderMapper()); + entity.setRealm(this.realm); + entity.setConfig(model.getConfig()); + + em.persist(entity); + this.realm.getIdentityProviderMappers().add(entity); + return entityToModel(entity); + } + + protected IdentityProviderMapperEntity getIdentityProviderMapperEntity(String id) { + for (IdentityProviderMapperEntity entity : this.realm.getIdentityProviderMappers()) { + if (entity.getId().equals(id)) { + return entity; + } + } + return null; + + } + + protected IdentityProviderMapperEntity getIdentityProviderMapperEntityByName(String alias, String name) { + for (IdentityProviderMapperEntity entity : this.realm.getIdentityProviderMappers()) { + if (entity.getIdentityProviderAlias().equals(alias) && entity.getName().equals(name)) { + return entity; + } + } + return null; + + } + + @Override + public void removeIdentityProviderMapper(IdentityProviderMapperModel mapping) { + IdentityProviderMapperEntity toDelete = getIdentityProviderMapperEntity(mapping.getId()); + if (toDelete != null) { + this.realm.getIdentityProviderMappers().remove(toDelete); + em.remove(toDelete); + } + + } + + @Override + public void updateIdentityProviderMapper(IdentityProviderMapperModel mapping) { + IdentityProviderMapperEntity entity = getIdentityProviderMapperEntity(mapping.getId()); + entity.setIdentityProviderAlias(mapping.getIdentityProviderAlias()); + entity.setIdentityProviderMapper(mapping.getIdentityProviderMapper()); + if (entity.getConfig() == null) { + entity.setConfig(mapping.getConfig()); + } else { + entity.getConfig().clear(); + entity.getConfig().putAll(mapping.getConfig()); + } + em.flush(); + + } + + @Override + public IdentityProviderMapperModel getIdentityProviderMapperById(String id) { + IdentityProviderMapperEntity entity = getIdentityProviderMapperEntity(id); + if (entity == null) return null; + return entityToModel(entity); + } + + @Override + public IdentityProviderMapperModel getIdentityProviderMapperByName(String alias, String name) { + IdentityProviderMapperEntity entity = getIdentityProviderMapperEntityByName(alias, name); + if (entity == null) return null; + return entityToModel(entity); + } + + protected IdentityProviderMapperModel entityToModel(IdentityProviderMapperEntity entity) { + IdentityProviderMapperModel mapping = new IdentityProviderMapperModel(); + mapping.setId(entity.getId()); + mapping.setName(entity.getName()); + mapping.setIdentityProviderAlias(entity.getIdentityProviderAlias()); + mapping.setIdentityProviderMapper(entity.getIdentityProviderMapper()); + Map config = new HashMap(); + if (entity.getConfig() != null) config.putAll(entity.getConfig()); + mapping.setConfig(config); + return mapping; + } } \ No newline at end of file diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/RoleAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/RoleAdapter.java index 28a1f47d02..16878550b6 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/RoleAdapter.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/RoleAdapter.java @@ -105,7 +105,7 @@ public class RoleAdapter implements RoleModel { @Override public RoleContainerModel getContainer() { if (role.isApplicationRole()) { - return realm.getApplicationById(role.getApplication().getId()); + return realm.getClientById(role.getApplication().getId()); } else { return realm; diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/UserAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/UserAdapter.java index 5ef06fa1ad..a51d0de21b 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/UserAdapter.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/UserAdapter.java @@ -1,6 +1,6 @@ package org.keycloak.models.jpa; -import org.keycloak.models.ApplicationModel; +import org.keycloak.models.ClientModel; import org.keycloak.models.PasswordPolicy; import org.keycloak.models.RealmModel; import org.keycloak.models.RoleContainerModel; @@ -363,14 +363,14 @@ public class UserAdapter implements UserModel { } @Override - public Set getApplicationRoleMappings(ApplicationModel app) { + public Set getClientRoleMappings(ClientModel app) { Set roleMappings = getRoleMappings(); Set roles = new HashSet(); for (RoleModel role : roleMappings) { RoleContainerModel container = role.getContainer(); - if (container instanceof ApplicationModel) { - ApplicationModel appModel = (ApplicationModel)container; + if (container instanceof ClientModel) { + ClientModel appModel = (ClientModel)container; if (appModel.getId().equals(app.getId())) { roles.add(role); } diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ApplicationEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ApplicationEntity.java deleted file mode 100755 index 48a9ff0a84..0000000000 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ApplicationEntity.java +++ /dev/null @@ -1,116 +0,0 @@ -package org.keycloak.models.jpa.entities; - -import javax.persistence.CascadeType; -import javax.persistence.CollectionTable; -import javax.persistence.Column; -import javax.persistence.ElementCollection; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.JoinColumn; -import javax.persistence.JoinTable; -import javax.persistence.MapKeyColumn; -import javax.persistence.OneToMany; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; - -/** - * @author Bill Burke - * @version $Revision: 1 $ - */ -@Entity -public class ApplicationEntity extends ClientEntity { - - @Column(name="SURROGATE_AUTH_REQUIRED") - private boolean surrogateAuthRequired; - - @Column(name="BASE_URL") - private String baseUrl; - - @Column(name="MANAGEMENT_URL") - private String managementUrl; - - @Column(name="BEARER_ONLY") - private boolean bearerOnly; - - @Column(name="NODE_REREG_TIMEOUT") - private int nodeReRegistrationTimeout; - - @OneToMany(fetch = FetchType.EAGER, cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "application") - Collection roles = new ArrayList(); - - @OneToMany(fetch = FetchType.LAZY, cascade ={CascadeType.REMOVE}, orphanRemoval = true) - @JoinTable(name="APPLICATION_DEFAULT_ROLES", joinColumns = { @JoinColumn(name="APPLICATION_ID")}, inverseJoinColumns = { @JoinColumn(name="ROLE_ID")}) - Collection defaultRoles = new ArrayList(); - - @ElementCollection - @MapKeyColumn(name="NAME") - @Column(name="VALUE") - @CollectionTable(name="APP_NODE_REGISTRATIONS", joinColumns={ @JoinColumn(name="APPLICATION_ID") }) - Map registeredNodes = new HashMap(); - - public boolean isSurrogateAuthRequired() { - return surrogateAuthRequired; - } - - public void setSurrogateAuthRequired(boolean surrogateAuthRequired) { - this.surrogateAuthRequired = surrogateAuthRequired; - } - - public String getBaseUrl() { - return baseUrl; - } - - public void setBaseUrl(String baseUrl) { - this.baseUrl = baseUrl; - } - - public String getManagementUrl() { - return managementUrl; - } - - public void setManagementUrl(String managementUrl) { - this.managementUrl = managementUrl; - } - - public Collection getRoles() { - return roles; - } - - public void setRoles(Collection roles) { - this.roles = roles; - } - - public Collection getDefaultRoles() { - return defaultRoles; - } - - public void setDefaultRoles(Collection defaultRoles) { - this.defaultRoles = defaultRoles; - } - - public boolean isBearerOnly() { - return bearerOnly; - } - - public void setBearerOnly(boolean bearerOnly) { - this.bearerOnly = bearerOnly; - } - - public int getNodeReRegistrationTimeout() { - return nodeReRegistrationTimeout; - } - - public void setNodeReRegistrationTimeout(int nodeReRegistrationTimeout) { - this.nodeReRegistrationTimeout = nodeReRegistrationTimeout; - } - - public Map getRegisteredNodes() { - return registeredNodes; - } - - public void setRegisteredNodes(Map registeredNodes) { - this.registeredNodes = registeredNodes; - } -} diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientEntity.java index e3c8bfdb43..f8a25f1832 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientEntity.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientEntity.java @@ -7,8 +7,6 @@ import javax.persistence.ElementCollection; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.Id; -import javax.persistence.Inheritance; -import javax.persistence.InheritanceType; import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.ManyToOne; @@ -28,14 +26,14 @@ import java.util.Set; * @version $Revision: 1 $ */ @Entity -@Inheritance(strategy = InheritanceType.SINGLE_TABLE) -@Table(name="CLIENT", uniqueConstraints = {@UniqueConstraint(columnNames = {"REALM_ID", "NAME"})}) -public abstract class ClientEntity { +@Table(name="CLIENT", uniqueConstraints = {@UniqueConstraint(columnNames = {"REALM_ID", "CLIENT_ID"})}) +public class ClientEntity { + @Id @Column(name="ID", length = 36) private String id; - @Column(name = "NAME") - private String name; + @Column(name = "CLIENT_ID") + private String clientId; @Column(name="ENABLED") private boolean enabled; @Column(name="SECRET") @@ -77,6 +75,40 @@ public abstract class ClientEntity { @OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "client") Collection protocolMappers = new ArrayList(); + @Column(name="SURROGATE_AUTH_REQUIRED") + private boolean surrogateAuthRequired; + + @Column(name="BASE_URL") + private String baseUrl; + + @Column(name="MANAGEMENT_URL") + private String managementUrl; + + @Column(name="DIRECT_GRANTS_ONLY") + protected boolean directGrantsOnly; + + @Column(name="BEARER_ONLY") + private boolean bearerOnly; + + @Column(name="CONSENT_REQUIRED") + private boolean consentRequired; + + @Column(name="NODE_REREG_TIMEOUT") + private int nodeReRegistrationTimeout; + + @OneToMany(fetch = FetchType.EAGER, cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "application") + Collection roles = new ArrayList(); + + @OneToMany(fetch = FetchType.LAZY, cascade ={CascadeType.REMOVE}, orphanRemoval = true) + @JoinTable(name="APPLICATION_DEFAULT_ROLES", joinColumns = { @JoinColumn(name="APPLICATION_ID")}, inverseJoinColumns = { @JoinColumn(name="ROLE_ID")}) + Collection defaultRoles = new ArrayList(); + + @ElementCollection + @MapKeyColumn(name="NAME") + @Column(name="VALUE") + @CollectionTable(name="APP_NODE_REGISTRATIONS", joinColumns={ @JoinColumn(name="APPLICATION_ID") }) + Map registeredNodes = new HashMap(); + public RealmEntity getRealm() { return realm; } @@ -101,12 +133,12 @@ public abstract class ClientEntity { this.enabled = enabled; } - public String getName() { - return name; + public String getClientId() { + return clientId; } - public void setName(String name) { - this.name = name; + public void setClientId(String clientId) { + this.clientId = clientId; } public Set getWebOrigins() { @@ -196,4 +228,84 @@ public abstract class ClientEntity { public void setProtocolMappers(Collection protocolMappers) { this.protocolMappers = protocolMappers; } + + public boolean isSurrogateAuthRequired() { + return surrogateAuthRequired; + } + + public void setSurrogateAuthRequired(boolean surrogateAuthRequired) { + this.surrogateAuthRequired = surrogateAuthRequired; + } + + public String getBaseUrl() { + return baseUrl; + } + + public void setBaseUrl(String baseUrl) { + this.baseUrl = baseUrl; + } + + public String getManagementUrl() { + return managementUrl; + } + + public void setManagementUrl(String managementUrl) { + this.managementUrl = managementUrl; + } + + public Collection getRoles() { + return roles; + } + + public void setRoles(Collection roles) { + this.roles = roles; + } + + public Collection getDefaultRoles() { + return defaultRoles; + } + + public void setDefaultRoles(Collection defaultRoles) { + this.defaultRoles = defaultRoles; + } + + public boolean isBearerOnly() { + return bearerOnly; + } + + public void setBearerOnly(boolean bearerOnly) { + this.bearerOnly = bearerOnly; + } + + public boolean isConsentRequired() { + return consentRequired; + } + + public void setConsentRequired(boolean consentRequired) { + this.consentRequired = consentRequired; + } + + public boolean isDirectGrantsOnly() { + return directGrantsOnly; + } + + public void setDirectGrantsOnly(boolean directGrantsOnly) { + this.directGrantsOnly = directGrantsOnly; + } + + public int getNodeReRegistrationTimeout() { + return nodeReRegistrationTimeout; + } + + public void setNodeReRegistrationTimeout(int nodeReRegistrationTimeout) { + this.nodeReRegistrationTimeout = nodeReRegistrationTimeout; + } + + public Map getRegisteredNodes() { + return registeredNodes; + } + + public void setRegisteredNodes(Map registeredNodes) { + this.registeredNodes = registeredNodes; + } } diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/OAuthClientEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/OAuthClientEntity.java deleted file mode 100755 index 191ec50f93..0000000000 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/OAuthClientEntity.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.keycloak.models.jpa.entities; - -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.NamedQueries; -import javax.persistence.NamedQuery; - -/** - * @author Bill Burke - * @version $Revision: 1 $ - */ -@NamedQueries({ - @NamedQuery(name="findOAuthClientByName", query="select o from OAuthClientEntity o where o.name=:name and o.realm = :realm"), - @NamedQuery(name="findOAuthClientByRealm", query="select o from OAuthClientEntity o where o.realm = :realm") - -}) -@Entity -public class OAuthClientEntity extends ClientEntity { - @Column(name="DIRECT_GRANTS_ONLY") - protected boolean directGrantsOnly; - - public boolean isDirectGrantsOnly() { - return directGrantsOnly; - } - - public void setDirectGrantsOnly(boolean directGrantsOnly) { - this.directGrantsOnly = directGrantsOnly; - } -} diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ProtocolMapperEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ProtocolMapperEntity.java index 7b2c323331..ccce0d9d30 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ProtocolMapperEntity.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ProtocolMapperEntity.java @@ -9,8 +9,6 @@ import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.MapKeyColumn; -import javax.persistence.NamedQueries; -import javax.persistence.NamedQuery; import javax.persistence.Table; import java.util.Map; diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RealmEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RealmEntity.java index a656f761ce..d39b62ed9d 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RealmEntity.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RealmEntity.java @@ -105,7 +105,7 @@ public class RealmEntity { @OneToMany(fetch = FetchType.LAZY, cascade ={CascadeType.REMOVE}, orphanRemoval = true) @JoinTable(name="REALM_APPLICATION", joinColumns={ @JoinColumn(name="REALM_ID") }, inverseJoinColumns={ @JoinColumn(name="APPLICATION_ID") }) - Collection applications = new ArrayList(); + Collection applications = new ArrayList(); @OneToMany(fetch = FetchType.LAZY, cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "realm") Collection roles = new ArrayList(); @@ -137,7 +137,7 @@ public class RealmEntity { @OneToOne @JoinColumn(name="MASTER_ADMIN_APP") - protected ApplicationEntity masterAdminApp; + protected ClientEntity masterAdminApp; @OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "realm") protected List identityProviders = new ArrayList(); @@ -318,11 +318,11 @@ public class RealmEntity { this.requiredCredentials = requiredCredentials; } - public Collection getApplications() { + public Collection getApplications() { return applications; } - public void setApplications(Collection applications) { + public void setApplications(Collection applications) { this.applications = applications; } @@ -437,11 +437,11 @@ public class RealmEntity { this.enabledEventTypes = enabledEventTypes; } - public ApplicationEntity getMasterAdminApp() { + public ClientEntity getMasterAdminApp() { return masterAdminApp; } - public void setMasterAdminApp(ApplicationEntity masterAdminApp) { + public void setMasterAdminApp(ClientEntity masterAdminApp) { this.masterAdminApp = masterAdminApp; } diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RoleEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RoleEntity.java index db40cea16a..ffbd711fa2 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RoleEntity.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RoleEntity.java @@ -51,7 +51,7 @@ public class RoleEntity { @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "APPLICATION") - private ApplicationEntity application; + private ClientEntity application; // Hack to ensure that either name+application or name+realm are unique. Needed due to MS-SQL as it don't allow multiple NULL values in the column, which is part of constraint @Column(name="APP_REALM_CONSTRAINT", length = 36) @@ -118,11 +118,11 @@ public class RoleEntity { this.appRealmConstraint = realm.getId(); } - public ApplicationEntity getApplication() { + public ClientEntity getApplication() { return application; } - public void setApplication(ApplicationEntity application) { + public void setApplication(ClientEntity application) { this.application = application; if (application != null) { this.appRealmConstraint = application.getId(); diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/ApplicationAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/ApplicationAdapter.java deleted file mode 100755 index 02e512a12a..0000000000 --- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/ApplicationAdapter.java +++ /dev/null @@ -1,275 +0,0 @@ -package org.keycloak.models.mongo.keycloak.adapters; - -import com.mongodb.DBObject; -import com.mongodb.QueryBuilder; -import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext; -import org.keycloak.models.ApplicationModel; -import org.keycloak.models.ClientModel; -import org.keycloak.models.KeycloakSession; -import org.keycloak.models.RealmModel; -import org.keycloak.models.RoleModel; -import org.keycloak.models.mongo.keycloak.entities.MongoApplicationEntity; -import org.keycloak.models.mongo.keycloak.entities.MongoRoleEntity; -import org.keycloak.models.mongo.utils.MongoModelUtils; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * @author Marek Posolda - */ -public class ApplicationAdapter extends ClientAdapter implements ApplicationModel { - - public ApplicationAdapter(KeycloakSession session, RealmModel realm, MongoApplicationEntity applicationEntity, MongoStoreInvocationContext invContext) { - super(session, realm, applicationEntity, invContext); - } - - @Override - public void updateApplication() { - updateMongoEntity(); - } - - @Override - public String getName() { - return getMongoEntity().getName(); - } - - @Override - public void setName(String name) { - getMongoEntity().setName(name); - updateMongoEntity(); - } - - @Override - public boolean isSurrogateAuthRequired() { - return getMongoEntity().isSurrogateAuthRequired(); - } - - @Override - public void setSurrogateAuthRequired(boolean surrogateAuthRequired) { - getMongoEntity().setSurrogateAuthRequired(surrogateAuthRequired); - updateMongoEntity(); - } - - @Override - public String getManagementUrl() { - return getMongoEntity().getManagementUrl(); - } - - @Override - public void setManagementUrl(String url) { - getMongoEntity().setManagementUrl(url); - updateMongoEntity(); - } - - @Override - public void setBaseUrl(String url) { - getMongoEntity().setBaseUrl(url); - updateMongoEntity(); - } - - @Override - public String getBaseUrl() { - return getMongoEntity().getBaseUrl(); - } - - @Override - public boolean isBearerOnly() { - return getMongoEntity().isBearerOnly(); - } - - @Override - public void setBearerOnly(boolean only) { - getMongoEntity().setBearerOnly(only); - updateMongoEntity(); - } - - @Override - public boolean isPublicClient() { - return getMongoEntity().isPublicClient(); - } - - @Override - public void setPublicClient(boolean flag) { - getMongoEntity().setPublicClient(flag); - updateMongoEntity(); - } - - @Override - public boolean isDirectGrantsOnly() { - return false; // applications can't be grant only - } - - @Override - public void setDirectGrantsOnly(boolean flag) { - // applications can't be grant only - } - - - @Override - public RoleAdapter getRole(String name) { - DBObject query = new QueryBuilder() - .and("name").is(name) - .and("applicationId").is(getId()) - .get(); - MongoRoleEntity role = getMongoStore().loadSingleEntity(MongoRoleEntity.class, query, invocationContext); - if (role == null) { - return null; - } else { - return new RoleAdapter(session, getRealm(), role, invocationContext); - } - } - - @Override - public RoleAdapter addRole(String name) { - return this.addRole(null, name); - } - - @Override - public RoleAdapter addRole(String id, String name) { - MongoRoleEntity roleEntity = new MongoRoleEntity(); - roleEntity.setId(id); - roleEntity.setName(name); - roleEntity.setApplicationId(getId()); - - getMongoStore().insertEntity(roleEntity, invocationContext); - - return new RoleAdapter(session, getRealm(), roleEntity, this, invocationContext); - } - - @Override - public boolean removeRole(RoleModel role) { - session.users().preRemove(getRealm(), role); - return getMongoStore().removeEntity(MongoRoleEntity.class, role.getId(), invocationContext); - } - - @Override - public Set getRoles() { - DBObject query = new QueryBuilder() - .and("applicationId").is(getId()) - .get(); - List roles = getMongoStore().loadEntities(MongoRoleEntity.class, query, invocationContext); - - Set result = new HashSet(); - for (MongoRoleEntity role : roles) { - result.add(new RoleAdapter(session, getRealm(), role, this, invocationContext)); - } - - return result; - } - - @Override - public boolean hasScope(RoleModel role) { - if (super.hasScope(role)) { - return true; - } - Set roles = getRoles(); - if (roles.contains(role)) return true; - - for (RoleModel mapping : roles) { - if (mapping.hasRole(role)) return true; - } - return false; - } - - @Override - public Set getApplicationScopeMappings(ClientModel client) { - Set result = new HashSet(); - List roles = MongoModelUtils.getAllScopesOfClient(client, invocationContext); - - for (MongoRoleEntity role : roles) { - if (getId().equals(role.getApplicationId())) { - result.add(new RoleAdapter(session, getRealm(), role, this, invocationContext)); - } - } - return result; - } - - @Override - public List getDefaultRoles() { - return getMongoEntity().getDefaultRoles(); - } - - @Override - public void addDefaultRole(String name) { - RoleModel role = getRole(name); - if (role == null) { - addRole(name); - } - - getMongoStore().pushItemToList(getMongoEntity(), "defaultRoles", name, true, invocationContext); - } - - @Override - public void updateDefaultRoles(String[] defaultRoles) { - List roleNames = new ArrayList(); - for (String roleName : defaultRoles) { - RoleModel role = getRole(roleName); - if (role == null) { - addRole(roleName); - } - - roleNames.add(roleName); - } - - getMongoEntity().setDefaultRoles(roleNames); - updateMongoEntity(); - } - - @Override - public int getNodeReRegistrationTimeout() { - return getMongoEntity().getNodeReRegistrationTimeout(); - } - - @Override - public void setNodeReRegistrationTimeout(int timeout) { - getMongoEntity().setNodeReRegistrationTimeout(timeout); - updateMongoEntity(); - } - - @Override - public Map getRegisteredNodes() { - return getMongoEntity().getRegisteredNodes() == null ? Collections.emptyMap() : Collections.unmodifiableMap(getMongoEntity().getRegisteredNodes()); - } - - @Override - public void registerNode(String nodeHost, int registrationTime) { - MongoApplicationEntity entity = getMongoEntity(); - if (entity.getRegisteredNodes() == null) { - entity.setRegisteredNodes(new HashMap()); - } - - entity.getRegisteredNodes().put(nodeHost, registrationTime); - updateMongoEntity(); - } - - @Override - public void unregisterNode(String nodeHost) { - MongoApplicationEntity entity = getMongoEntity(); - if (entity.getRegisteredNodes() == null) return; - - entity.getRegisteredNodes().remove(nodeHost); - updateMongoEntity(); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || !(o instanceof ApplicationModel)) return false; - - ApplicationModel that = (ApplicationModel) o; - return that.getId().equals(getId()); - } - - @Override - public int hashCode() { - return getId().hashCode(); - } - - -} diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/ClientAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/ClientAdapter.java index 38c40f8f39..803cedf417 100755 --- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/ClientAdapter.java +++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/ClientAdapter.java @@ -1,445 +1,672 @@ -package org.keycloak.models.mongo.keycloak.adapters; - -import org.keycloak.connections.mongo.api.MongoIdentifiableEntity; -import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext; -import org.keycloak.models.ClientIdentityProviderMappingModel; -import org.keycloak.models.ClientModel; -import org.keycloak.models.KeycloakSession; -import org.keycloak.models.ProtocolMapperModel; -import org.keycloak.models.RealmModel; -import org.keycloak.models.RealmProvider; -import org.keycloak.models.RoleModel; -import org.keycloak.models.entities.ClientEntity; -import org.keycloak.models.entities.ClientIdentityProviderMappingEntity; -import org.keycloak.models.entities.ProtocolMapperEntity; -import org.keycloak.models.mongo.keycloak.entities.MongoRoleEntity; -import org.keycloak.models.mongo.utils.MongoModelUtils; -import org.keycloak.models.utils.KeycloakModelUtils; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * @author Marek Posolda - */ -public abstract class ClientAdapter extends AbstractMongoAdapter implements ClientModel { - - protected final T clientEntity; - private final RealmModel realm; - protected KeycloakSession session; - - public ClientAdapter(KeycloakSession session, RealmModel realm, T clientEntity, MongoStoreInvocationContext invContext) { - super(invContext); - this.clientEntity = clientEntity; - this.realm = realm; - this.session = session; - } - - @Override - public T getMongoEntity() { - return clientEntity; - } - - // ClientEntity doesn't extend MongoIdentifiableEntity - public ClientEntity getMongoEntityAsClient() { - return (ClientEntity)getMongoEntity(); - } - - @Override - public String getId() { - return getMongoEntity().getId(); - } - - @Override - public String getClientId() { - return getMongoEntityAsClient().getName(); - } - - @Override - public Set getWebOrigins() { - Set result = new HashSet(); - if (getMongoEntityAsClient().getWebOrigins() != null) { - result.addAll(getMongoEntityAsClient().getWebOrigins()); - } - return result; - } - - @Override - public void setWebOrigins(Set webOrigins) { - List result = new ArrayList(); - result.addAll(webOrigins); - getMongoEntityAsClient().setWebOrigins(result); - updateMongoEntity(); - } - - @Override - public void addWebOrigin(String webOrigin) { - getMongoStore().pushItemToList(clientEntity, "webOrigins", webOrigin, true, invocationContext); - } - - @Override - public void removeWebOrigin(String webOrigin) { - getMongoStore().pullItemFromList(clientEntity, "webOrigins", webOrigin, invocationContext); - } - - @Override - public Set getRedirectUris() { - Set result = new HashSet(); - if (getMongoEntityAsClient().getRedirectUris() != null) { - result.addAll(getMongoEntityAsClient().getRedirectUris()); - } - return result; - } - - @Override - public void setRedirectUris(Set redirectUris) { - List result = new ArrayList(); - result.addAll(redirectUris); - getMongoEntityAsClient().setRedirectUris(result); - updateMongoEntity(); - } - - @Override - public void addRedirectUri(String redirectUri) { - getMongoStore().pushItemToList(clientEntity, "redirectUris", redirectUri, true, invocationContext); - } - - @Override - public void removeRedirectUri(String redirectUri) { - getMongoStore().pullItemFromList(clientEntity, "redirectUris", redirectUri, invocationContext); - } - - @Override - public boolean isEnabled() { - return getMongoEntityAsClient().isEnabled(); - } - - @Override - public void setEnabled(boolean enabled) { - getMongoEntityAsClient().setEnabled(enabled); - updateMongoEntity(); - } - - @Override - public boolean validateSecret(String secret) { - return secret.equals(getMongoEntityAsClient().getSecret()); - } - - @Override - public String getSecret() { - return getMongoEntityAsClient().getSecret(); - } - - @Override - public void setSecret(String secret) { - getMongoEntityAsClient().setSecret(secret); - updateMongoEntity(); - } - - @Override - public boolean isPublicClient() { - return getMongoEntityAsClient().isPublicClient(); - } - - @Override - public void setPublicClient(boolean flag) { - getMongoEntityAsClient().setPublicClient(flag); - updateMongoEntity(); - } - - - @Override - public boolean isFrontchannelLogout() { - return getMongoEntityAsClient().isFrontchannelLogout(); - } - - @Override - public void setFrontchannelLogout(boolean flag) { - getMongoEntityAsClient().setFrontchannelLogout(flag); - updateMongoEntity(); - } - - @Override - public boolean isFullScopeAllowed() { - return getMongoEntityAsClient().isFullScopeAllowed(); - } - - @Override - public void setFullScopeAllowed(boolean value) { - getMongoEntityAsClient().setFullScopeAllowed(value); - updateMongoEntity(); - - } - - @Override - public RealmModel getRealm() { - return realm; - } - - @Override - public int getNotBefore() { - return getMongoEntityAsClient().getNotBefore(); - } - - @Override - public void setNotBefore(int notBefore) { - getMongoEntityAsClient().setNotBefore(notBefore); - updateMongoEntity(); - } - - @Override - public Set getScopeMappings() { - Set result = new HashSet(); - List roles = MongoModelUtils.getAllScopesOfClient(this, invocationContext); - - for (MongoRoleEntity role : roles) { - if (realm.getId().equals(role.getRealmId())) { - result.add(new RoleAdapter(session, realm, role, realm, invocationContext)); - } else { - // Likely applicationRole, but we don't have this application yet - result.add(new RoleAdapter(session, realm, role, invocationContext)); - } - } - return result; - } - - @Override - public Set getRealmScopeMappings() { - Set allScopes = getScopeMappings(); - - // Filter to retrieve just realm roles TODO: Maybe improve to avoid filter programmatically... Maybe have separate fields for realmRoles and appRoles on user? - Set realmRoles = new HashSet(); - for (RoleModel role : allScopes) { - MongoRoleEntity roleEntity = ((RoleAdapter) role).getRole(); - - if (realm.getId().equals(roleEntity.getRealmId())) { - realmRoles.add(role); - } - } - return realmRoles; - } - - @Override - public boolean hasScope(RoleModel role) { - if (isFullScopeAllowed()) return true; - Set roles = getScopeMappings(); - if (roles.contains(role)) return true; - - for (RoleModel mapping : roles) { - if (mapping.hasRole(role)) return true; - } - return false; - } - - - @Override - public void addScopeMapping(RoleModel role) { - getMongoStore().pushItemToList(this.getMongoEntity(), "scopeIds", role.getId(), true, invocationContext); - } - - @Override - public void deleteScopeMapping(RoleModel role) { - getMongoStore().pullItemFromList(this.getMongoEntity(), "scopeIds", role.getId(), invocationContext); - } - - @Override - public String getProtocol() { - return getMongoEntityAsClient().getProtocol(); - } - - @Override - public void setProtocol(String protocol) { - getMongoEntityAsClient().setProtocol(protocol); - updateMongoEntity(); - - } - - @Override - public void setAttribute(String name, String value) { - getMongoEntityAsClient().getAttributes().put(name, value); - updateMongoEntity(); - - } - - @Override - public void removeAttribute(String name) { - getMongoEntityAsClient().getAttributes().remove(name); - updateMongoEntity(); - } - - @Override - public String getAttribute(String name) { - return getMongoEntityAsClient().getAttributes().get(name); - } - - @Override - public Map getAttributes() { - Map copy = new HashMap(); - copy.putAll(getMongoEntityAsClient().getAttributes()); - return copy; - } - - @Override - public Set getProtocolMappers() { - Set result = new HashSet(); - for (ProtocolMapperEntity entity : getMongoEntityAsClient().getProtocolMappers()) { - ProtocolMapperModel mapping = new ProtocolMapperModel(); - mapping.setId(entity.getId()); - mapping.setName(entity.getName()); - mapping.setProtocol(entity.getProtocol()); - mapping.setProtocolMapper(entity.getProtocolMapper()); - mapping.setConsentRequired(entity.isConsentRequired()); - mapping.setConsentText(entity.getConsentText()); - Map config = new HashMap(); - if (entity.getConfig() != null) { - config.putAll(entity.getConfig()); - } - mapping.setConfig(config); - result.add(mapping); - } - return result; - } - - @Override - public ProtocolMapperModel addProtocolMapper(ProtocolMapperModel model) { - if (getProtocolMapperByName(model.getProtocol(), model.getName()) != null) { - throw new RuntimeException("protocol mapper name must be unique per protocol"); - } - ProtocolMapperEntity entity = new ProtocolMapperEntity(); - entity.setId(KeycloakModelUtils.generateId()); - entity.setProtocol(model.getProtocol()); - entity.setName(model.getName()); - entity.setProtocolMapper(model.getProtocolMapper()); - entity.setConfig(model.getConfig()); - entity.setConsentRequired(model.isConsentRequired()); - entity.setConsentText(model.getConsentText()); - getMongoEntityAsClient().getProtocolMappers().add(entity); - updateMongoEntity(); - return entityToModel(entity); - } - - @Override - public void removeProtocolMapper(ProtocolMapperModel mapping) { - for (ProtocolMapperEntity entity : getMongoEntityAsClient().getProtocolMappers()) { - if (entity.getId().equals(mapping.getId())) { - getMongoEntityAsClient().getProtocolMappers().remove(entity); - updateMongoEntity(); - break; - } - } - - } - - protected ProtocolMapperEntity getProtocolMapperyEntityById(String id) { - for (ProtocolMapperEntity entity : getMongoEntityAsClient().getProtocolMappers()) { - if (entity.getId().equals(id)) { - return entity; - } - } - return null; - - } - protected ProtocolMapperEntity getProtocolMapperEntityByName(String protocol, String name) { - for (ProtocolMapperEntity entity : getMongoEntityAsClient().getProtocolMappers()) { - if (entity.getProtocol().equals(protocol) && entity.getName().equals(name)) { - return entity; - } - } - return null; - - } - - - @Override - public void updateProtocolMapper(ProtocolMapperModel mapping) { - ProtocolMapperEntity entity = getProtocolMapperyEntityById(mapping.getId()); - entity.setProtocolMapper(mapping.getProtocolMapper()); - entity.setConsentRequired(mapping.isConsentRequired()); - entity.setConsentText(mapping.getConsentText()); - if (entity.getConfig() != null) { - entity.getConfig().clear(); - entity.getConfig().putAll(mapping.getConfig()); - } else { - entity.setConfig(mapping.getConfig()); - } - updateMongoEntity(); - - } - - @Override - public ProtocolMapperModel getProtocolMapperById(String id) { - ProtocolMapperEntity entity = getProtocolMapperyEntityById(id); - if (entity == null) return null; - return entityToModel(entity); - } - - @Override - public ProtocolMapperModel getProtocolMapperByName(String protocol, String name) { - ProtocolMapperEntity entity = getProtocolMapperEntityByName(protocol, name); - if (entity == null) return null; - return entityToModel(entity); - } - - protected ProtocolMapperModel entityToModel(ProtocolMapperEntity entity) { - ProtocolMapperModel mapping = new ProtocolMapperModel(); - mapping.setId(entity.getId()); - mapping.setName(entity.getName()); - mapping.setProtocol(entity.getProtocol()); - mapping.setProtocolMapper(entity.getProtocolMapper()); - mapping.setConsentRequired(entity.isConsentRequired()); - mapping.setConsentText(entity.getConsentText()); - Map config = new HashMap(); - if (entity.getConfig() != null) config.putAll(entity.getConfig()); - mapping.setConfig(config); - return mapping; - } - - - @Override - public void updateIdentityProviders(List identityProviders) { - List stored = new ArrayList(); - - for (ClientIdentityProviderMappingModel model : identityProviders) { - ClientIdentityProviderMappingEntity entity = new ClientIdentityProviderMappingEntity(); - - entity.setId(model.getIdentityProvider()); - entity.setRetrieveToken(model.isRetrieveToken()); - stored.add(entity); - } - - getMongoEntityAsClient().setIdentityProviders(stored); - updateMongoEntity(); - } - - @Override - public List getIdentityProviders() { - List models = new ArrayList(); - - for (ClientIdentityProviderMappingEntity entity : getMongoEntityAsClient().getIdentityProviders()) { - ClientIdentityProviderMappingModel model = new ClientIdentityProviderMappingModel(); - - model.setIdentityProvider(entity.getId()); - model.setRetrieveToken(entity.isRetrieveToken()); - - models.add(model); - } - - return models; - } - - @Override - public boolean isAllowedRetrieveTokenFromIdentityProvider(String providerId) { - for (ClientIdentityProviderMappingEntity identityProviderMappingModel : getMongoEntityAsClient().getIdentityProviders()) { - if (identityProviderMappingModel.getId().equals(providerId)) { - return identityProviderMappingModel.isRetrieveToken(); - } - } - - return false; - } - -} +package org.keycloak.models.mongo.keycloak.adapters; + +import com.mongodb.DBObject; +import com.mongodb.QueryBuilder; +import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext; +import org.keycloak.models.ClientModel; +import org.keycloak.models.ClientIdentityProviderMappingModel; +import org.keycloak.models.KeycloakSession; +import org.keycloak.models.ProtocolMapperModel; +import org.keycloak.models.RealmModel; +import org.keycloak.models.RoleModel; +import org.keycloak.models.entities.ClientIdentityProviderMappingEntity; +import org.keycloak.models.entities.ProtocolMapperEntity; +import org.keycloak.models.mongo.keycloak.entities.MongoClientEntity; +import org.keycloak.models.mongo.keycloak.entities.MongoRoleEntity; +import org.keycloak.models.mongo.utils.MongoModelUtils; +import org.keycloak.models.utils.KeycloakModelUtils; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * @author Marek Posolda + */ +public class ClientAdapter extends AbstractMongoAdapter implements ClientModel { + + protected final MongoClientEntity applicationEntity; + private final RealmModel realm; + protected KeycloakSession session; + + public ClientAdapter(KeycloakSession session, RealmModel realm, MongoClientEntity applicationEntity, MongoStoreInvocationContext invContext) { + super(invContext); + this.session = session; + this.realm = realm; + this.applicationEntity = applicationEntity; + } + + @Override + public MongoClientEntity getMongoEntity() { + return applicationEntity; + } + + @Override + public void updateClient() { + updateMongoEntity(); + } + + + @Override + public String getId() { + return getMongoEntity().getId(); + } + + @Override + public String getClientId() { + return getMongoEntity().getClientId(); + } + + @Override + public void setClientId(String clientId) { + getMongoEntity().setClientId(clientId); + updateMongoEntity(); + } + + @Override + public Set getWebOrigins() { + Set result = new HashSet(); + if (getMongoEntity().getWebOrigins() != null) { + result.addAll(getMongoEntity().getWebOrigins()); + } + return result; + } + + @Override + public void setWebOrigins(Set webOrigins) { + List result = new ArrayList(); + result.addAll(webOrigins); + getMongoEntity().setWebOrigins(result); + updateMongoEntity(); + } + + @Override + public void addWebOrigin(String webOrigin) { + getMongoStore().pushItemToList(applicationEntity, "webOrigins", webOrigin, true, invocationContext); + } + + @Override + public void removeWebOrigin(String webOrigin) { + getMongoStore().pullItemFromList(applicationEntity, "webOrigins", webOrigin, invocationContext); + } + + @Override + public Set getRedirectUris() { + Set result = new HashSet(); + if (getMongoEntity().getRedirectUris() != null) { + result.addAll(getMongoEntity().getRedirectUris()); + } + return result; + } + + @Override + public void setRedirectUris(Set redirectUris) { + List result = new ArrayList(); + result.addAll(redirectUris); + getMongoEntity().setRedirectUris(result); + updateMongoEntity(); + } + + @Override + public void addRedirectUri(String redirectUri) { + getMongoStore().pushItemToList(applicationEntity, "redirectUris", redirectUri, true, invocationContext); + } + + @Override + public void removeRedirectUri(String redirectUri) { + getMongoStore().pullItemFromList(applicationEntity, "redirectUris", redirectUri, invocationContext); + } + + @Override + public boolean isEnabled() { + return getMongoEntity().isEnabled(); + } + + @Override + public void setEnabled(boolean enabled) { + getMongoEntity().setEnabled(enabled); + updateMongoEntity(); + } + + @Override + public boolean validateSecret(String secret) { + return secret.equals(getMongoEntity().getSecret()); + } + + @Override + public String getSecret() { + return getMongoEntity().getSecret(); + } + + @Override + public void setSecret(String secret) { + getMongoEntity().setSecret(secret); + updateMongoEntity(); + } + + @Override + public boolean isPublicClient() { + return getMongoEntity().isPublicClient(); + } + + @Override + public void setPublicClient(boolean flag) { + getMongoEntity().setPublicClient(flag); + updateMongoEntity(); + } + + + @Override + public boolean isFrontchannelLogout() { + return getMongoEntity().isFrontchannelLogout(); + } + + @Override + public void setFrontchannelLogout(boolean flag) { + getMongoEntity().setFrontchannelLogout(flag); + updateMongoEntity(); + } + + @Override + public boolean isFullScopeAllowed() { + return getMongoEntity().isFullScopeAllowed(); + } + + @Override + public void setFullScopeAllowed(boolean value) { + getMongoEntity().setFullScopeAllowed(value); + updateMongoEntity(); + + } + + @Override + public RealmModel getRealm() { + return realm; + } + + @Override + public int getNotBefore() { + return getMongoEntity().getNotBefore(); + } + + @Override + public void setNotBefore(int notBefore) { + getMongoEntity().setNotBefore(notBefore); + updateMongoEntity(); + } + + @Override + public Set getScopeMappings() { + Set result = new HashSet(); + List roles = MongoModelUtils.getAllScopesOfClient(this, invocationContext); + + for (MongoRoleEntity role : roles) { + if (realm.getId().equals(role.getRealmId())) { + result.add(new RoleAdapter(session, realm, role, realm, invocationContext)); + } else { + // Likely applicationRole, but we don't have this application yet + result.add(new RoleAdapter(session, realm, role, invocationContext)); + } + } + return result; + } + + @Override + public Set getRealmScopeMappings() { + Set allScopes = getScopeMappings(); + + // Filter to retrieve just realm roles TODO: Maybe improve to avoid filter programmatically... Maybe have separate fields for realmRoles and appRoles on user? + Set realmRoles = new HashSet(); + for (RoleModel role : allScopes) { + MongoRoleEntity roleEntity = ((RoleAdapter) role).getRole(); + + if (realm.getId().equals(roleEntity.getRealmId())) { + realmRoles.add(role); + } + } + return realmRoles; + } + + @Override + public void addScopeMapping(RoleModel role) { + getMongoStore().pushItemToList(this.getMongoEntity(), "scopeIds", role.getId(), true, invocationContext); + } + + @Override + public void deleteScopeMapping(RoleModel role) { + getMongoStore().pullItemFromList(this.getMongoEntity(), "scopeIds", role.getId(), invocationContext); + } + + @Override + public String getProtocol() { + return getMongoEntity().getProtocol(); + } + + @Override + public void setProtocol(String protocol) { + getMongoEntity().setProtocol(protocol); + updateMongoEntity(); + + } + + @Override + public void setAttribute(String name, String value) { + getMongoEntity().getAttributes().put(name, value); + updateMongoEntity(); + + } + + @Override + public void removeAttribute(String name) { + getMongoEntity().getAttributes().remove(name); + updateMongoEntity(); + } + + @Override + public String getAttribute(String name) { + return getMongoEntity().getAttributes().get(name); + } + + @Override + public Map getAttributes() { + Map copy = new HashMap(); + copy.putAll(getMongoEntity().getAttributes()); + return copy; + } + + @Override + public Set getProtocolMappers() { + Set result = new HashSet(); + for (ProtocolMapperEntity entity : getMongoEntity().getProtocolMappers()) { + ProtocolMapperModel mapping = new ProtocolMapperModel(); + mapping.setId(entity.getId()); + mapping.setName(entity.getName()); + mapping.setProtocol(entity.getProtocol()); + mapping.setProtocolMapper(entity.getProtocolMapper()); + mapping.setConsentRequired(entity.isConsentRequired()); + mapping.setConsentText(entity.getConsentText()); + Map config = new HashMap(); + if (entity.getConfig() != null) { + config.putAll(entity.getConfig()); + } + mapping.setConfig(config); + result.add(mapping); + } + return result; + } + + @Override + public ProtocolMapperModel addProtocolMapper(ProtocolMapperModel model) { + if (getProtocolMapperByName(model.getProtocol(), model.getName()) != null) { + throw new RuntimeException("protocol mapper name must be unique per protocol"); + } + ProtocolMapperEntity entity = new ProtocolMapperEntity(); + entity.setId(KeycloakModelUtils.generateId()); + entity.setProtocol(model.getProtocol()); + entity.setName(model.getName()); + entity.setProtocolMapper(model.getProtocolMapper()); + entity.setConfig(model.getConfig()); + entity.setConsentRequired(model.isConsentRequired()); + entity.setConsentText(model.getConsentText()); + getMongoEntity().getProtocolMappers().add(entity); + updateMongoEntity(); + return entityToModel(entity); + } + + @Override + public void removeProtocolMapper(ProtocolMapperModel mapping) { + for (ProtocolMapperEntity entity : getMongoEntity().getProtocolMappers()) { + if (entity.getId().equals(mapping.getId())) { + getMongoEntity().getProtocolMappers().remove(entity); + updateMongoEntity(); + break; + } + } + + } + + protected ProtocolMapperEntity getProtocolMapperyEntityById(String id) { + for (ProtocolMapperEntity entity : getMongoEntity().getProtocolMappers()) { + if (entity.getId().equals(id)) { + return entity; + } + } + return null; + + } + protected ProtocolMapperEntity getProtocolMapperEntityByName(String protocol, String name) { + for (ProtocolMapperEntity entity : getMongoEntity().getProtocolMappers()) { + if (entity.getProtocol().equals(protocol) && entity.getName().equals(name)) { + return entity; + } + } + return null; + + } + + + @Override + public void updateProtocolMapper(ProtocolMapperModel mapping) { + ProtocolMapperEntity entity = getProtocolMapperyEntityById(mapping.getId()); + entity.setProtocolMapper(mapping.getProtocolMapper()); + entity.setConsentRequired(mapping.isConsentRequired()); + entity.setConsentText(mapping.getConsentText()); + if (entity.getConfig() != null) { + entity.getConfig().clear(); + entity.getConfig().putAll(mapping.getConfig()); + } else { + entity.setConfig(mapping.getConfig()); + } + updateMongoEntity(); + + } + + @Override + public ProtocolMapperModel getProtocolMapperById(String id) { + ProtocolMapperEntity entity = getProtocolMapperyEntityById(id); + if (entity == null) return null; + return entityToModel(entity); + } + + @Override + public ProtocolMapperModel getProtocolMapperByName(String protocol, String name) { + ProtocolMapperEntity entity = getProtocolMapperEntityByName(protocol, name); + if (entity == null) return null; + return entityToModel(entity); + } + + protected ProtocolMapperModel entityToModel(ProtocolMapperEntity entity) { + ProtocolMapperModel mapping = new ProtocolMapperModel(); + mapping.setId(entity.getId()); + mapping.setName(entity.getName()); + mapping.setProtocol(entity.getProtocol()); + mapping.setProtocolMapper(entity.getProtocolMapper()); + mapping.setConsentRequired(entity.isConsentRequired()); + mapping.setConsentText(entity.getConsentText()); + Map config = new HashMap(); + if (entity.getConfig() != null) config.putAll(entity.getConfig()); + mapping.setConfig(config); + return mapping; + } + + + @Override + public void updateIdentityProviders(List identityProviders) { + List stored = new ArrayList(); + + for (ClientIdentityProviderMappingModel model : identityProviders) { + ClientIdentityProviderMappingEntity entity = new ClientIdentityProviderMappingEntity(); + + entity.setId(model.getIdentityProvider()); + entity.setRetrieveToken(model.isRetrieveToken()); + stored.add(entity); + } + + getMongoEntity().setIdentityProviders(stored); + updateMongoEntity(); + } + + @Override + public List getIdentityProviders() { + List models = new ArrayList(); + + for (ClientIdentityProviderMappingEntity entity : getMongoEntity().getIdentityProviders()) { + ClientIdentityProviderMappingModel model = new ClientIdentityProviderMappingModel(); + + model.setIdentityProvider(entity.getId()); + model.setRetrieveToken(entity.isRetrieveToken()); + + models.add(model); + } + + return models; + } + + @Override + public boolean isAllowedRetrieveTokenFromIdentityProvider(String providerId) { + for (ClientIdentityProviderMappingEntity identityProviderMappingModel : getMongoEntity().getIdentityProviders()) { + if (identityProviderMappingModel.getId().equals(providerId)) { + return identityProviderMappingModel.isRetrieveToken(); + } + } + + return false; + } + + @Override + public boolean isSurrogateAuthRequired() { + return getMongoEntity().isSurrogateAuthRequired(); + } + + @Override + public void setSurrogateAuthRequired(boolean surrogateAuthRequired) { + getMongoEntity().setSurrogateAuthRequired(surrogateAuthRequired); + updateMongoEntity(); + } + + @Override + public String getManagementUrl() { + return getMongoEntity().getManagementUrl(); + } + + @Override + public void setManagementUrl(String url) { + getMongoEntity().setManagementUrl(url); + updateMongoEntity(); + } + + @Override + public void setBaseUrl(String url) { + getMongoEntity().setBaseUrl(url); + updateMongoEntity(); + } + + @Override + public String getBaseUrl() { + return getMongoEntity().getBaseUrl(); + } + + @Override + public boolean isBearerOnly() { + return getMongoEntity().isBearerOnly(); + } + + @Override + public void setBearerOnly(boolean only) { + getMongoEntity().setBearerOnly(only); + updateMongoEntity(); + } + + @Override + public boolean isConsentRequired() { + return getMongoEntity().isConsentRequired(); + } + + @Override + public void setConsentRequired(boolean consentRequired) { + getMongoEntity().setConsentRequired(consentRequired); + updateMongoEntity(); + } + + @Override + public boolean isDirectGrantsOnly() { + return getMongoEntity().isDirectGrantsOnly(); + } + + @Override + public void setDirectGrantsOnly(boolean flag) { + getMongoEntity().setDirectGrantsOnly(flag); + updateMongoEntity(); + } + + @Override + public RoleAdapter getRole(String name) { + DBObject query = new QueryBuilder() + .and("name").is(name) + .and("clientId").is(getId()) + .get(); + MongoRoleEntity role = getMongoStore().loadSingleEntity(MongoRoleEntity.class, query, invocationContext); + if (role == null) { + return null; + } else { + return new RoleAdapter(session, getRealm(), role, invocationContext); + } + } + + @Override + public RoleAdapter addRole(String name) { + return this.addRole(null, name); + } + + @Override + public RoleAdapter addRole(String id, String name) { + MongoRoleEntity roleEntity = new MongoRoleEntity(); + roleEntity.setId(id); + roleEntity.setName(name); + roleEntity.setClientId(getId()); + + getMongoStore().insertEntity(roleEntity, invocationContext); + + return new RoleAdapter(session, getRealm(), roleEntity, this, invocationContext); + } + + @Override + public boolean removeRole(RoleModel role) { + session.users().preRemove(getRealm(), role); + return getMongoStore().removeEntity(MongoRoleEntity.class, role.getId(), invocationContext); + } + + @Override + public Set getRoles() { + DBObject query = new QueryBuilder() + .and("clientId").is(getId()) + .get(); + List roles = getMongoStore().loadEntities(MongoRoleEntity.class, query, invocationContext); + + Set result = new HashSet(); + for (MongoRoleEntity role : roles) { + result.add(new RoleAdapter(session, getRealm(), role, this, invocationContext)); + } + + return result; + } + + @Override + public boolean hasScope(RoleModel role) { + if (isFullScopeAllowed()) return true; + Set roles = getScopeMappings(); + if (roles.contains(role)) return true; + + for (RoleModel mapping : roles) { + if (mapping.hasRole(role)) return true; + } + + roles = getRoles(); + if (roles.contains(role)) return true; + + for (RoleModel mapping : roles) { + if (mapping.hasRole(role)) return true; + } + return false; + } + + @Override + public Set getClientScopeMappings(ClientModel client) { + Set result = new HashSet(); + List roles = MongoModelUtils.getAllScopesOfClient(client, invocationContext); + + for (MongoRoleEntity role : roles) { + if (getId().equals(role.getClientId())) { + result.add(new RoleAdapter(session, getRealm(), role, this, invocationContext)); + } + } + return result; + } + + @Override + public List getDefaultRoles() { + return getMongoEntity().getDefaultRoles(); + } + + @Override + public void addDefaultRole(String name) { + RoleModel role = getRole(name); + if (role == null) { + addRole(name); + } + + getMongoStore().pushItemToList(getMongoEntity(), "defaultRoles", name, true, invocationContext); + } + + @Override + public void updateDefaultRoles(String[] defaultRoles) { + List roleNames = new ArrayList(); + for (String roleName : defaultRoles) { + RoleModel role = getRole(roleName); + if (role == null) { + addRole(roleName); + } + + roleNames.add(roleName); + } + + getMongoEntity().setDefaultRoles(roleNames); + updateMongoEntity(); + } + + @Override + public int getNodeReRegistrationTimeout() { + return getMongoEntity().getNodeReRegistrationTimeout(); + } + + @Override + public void setNodeReRegistrationTimeout(int timeout) { + getMongoEntity().setNodeReRegistrationTimeout(timeout); + updateMongoEntity(); + } + + @Override + public Map getRegisteredNodes() { + return getMongoEntity().getRegisteredNodes() == null ? Collections.emptyMap() : Collections.unmodifiableMap(getMongoEntity().getRegisteredNodes()); + } + + @Override + public void registerNode(String nodeHost, int registrationTime) { + MongoClientEntity entity = getMongoEntity(); + if (entity.getRegisteredNodes() == null) { + entity.setRegisteredNodes(new HashMap()); + } + + entity.getRegisteredNodes().put(nodeHost, registrationTime); + updateMongoEntity(); + } + + @Override + public void unregisterNode(String nodeHost) { + MongoClientEntity entity = getMongoEntity(); + if (entity.getRegisteredNodes() == null) return; + + entity.getRegisteredNodes().remove(nodeHost); + updateMongoEntity(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || !(o instanceof ClientModel)) return false; + + ClientModel that = (ClientModel) o; + return that.getId().equals(getId()); + } + + @Override + public int hashCode() { + return getId().hashCode(); + } + + +} diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoRealmProvider.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoRealmProvider.java index 61865d6e6e..c8bdb389ed 100755 --- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoRealmProvider.java +++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoRealmProvider.java @@ -5,14 +5,12 @@ import com.mongodb.DBObject; import com.mongodb.QueryBuilder; import org.keycloak.connections.mongo.api.MongoStore; import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext; -import org.keycloak.models.ApplicationModel; +import org.keycloak.models.ClientModel; import org.keycloak.models.KeycloakSession; -import org.keycloak.models.OAuthClientModel; import org.keycloak.models.RealmModel; import org.keycloak.models.RealmProvider; import org.keycloak.models.RoleModel; -import org.keycloak.models.mongo.keycloak.entities.MongoApplicationEntity; -import org.keycloak.models.mongo.keycloak.entities.MongoOAuthClientEntity; +import org.keycloak.models.mongo.keycloak.entities.MongoClientEntity; import org.keycloak.models.mongo.keycloak.entities.MongoRealmEntity; import org.keycloak.models.mongo.keycloak.entities.MongoRoleEntity; import org.keycloak.models.utils.KeycloakModelUtils; @@ -107,30 +105,20 @@ public class MongoRealmProvider implements RealmProvider { MongoRoleEntity role = getMongoStore().loadEntity(MongoRoleEntity.class, id, invocationContext); if (role == null) return null; if (role.getRealmId() != null && !role.getRealmId().equals(realm.getId())) return null; - if (role.getApplicationId() != null && realm.getApplicationById(role.getApplicationId()) == null) return null; + if (role.getClientId() != null && realm.getClientById(role.getClientId()) == null) return null; return new RoleAdapter(session, realm, role, null, invocationContext); } @Override - public ApplicationModel getApplicationById(String id, RealmModel realm) { - MongoApplicationEntity appData = getMongoStore().loadEntity(MongoApplicationEntity.class, id, invocationContext); + public ClientModel getClientById(String id, RealmModel realm) { + MongoClientEntity appData = getMongoStore().loadEntity(MongoClientEntity.class, id, invocationContext); // Check if application belongs to this realm if (appData == null || !realm.getId().equals(appData.getRealmId())) { return null; } - return new ApplicationAdapter(session, realm, appData, invocationContext); - } - - @Override - public OAuthClientModel getOAuthClientById(String id, RealmModel realm) { - MongoOAuthClientEntity clientEntity = getMongoStore().loadEntity(MongoOAuthClientEntity.class, id, invocationContext); - - // Check if client belongs to this realm - if (clientEntity == null || !realm.getId().equals(clientEntity.getRealmId())) return null; - - return new OAuthClientAdapter(session, realm, clientEntity, invocationContext); + return new ClientAdapter(session, realm, appData, invocationContext); } } diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoUserProvider.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoUserProvider.java index bcae24de1e..862e387a74 100755 --- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoUserProvider.java +++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoUserProvider.java @@ -5,7 +5,7 @@ import com.mongodb.DBObject; import com.mongodb.QueryBuilder; import org.keycloak.connections.mongo.api.MongoStore; import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext; -import org.keycloak.models.ApplicationModel; +import org.keycloak.models.ClientModel; import org.keycloak.models.CredentialValidationOutput; import org.keycloak.models.FederatedIdentityModel; import org.keycloak.models.KeycloakSession; @@ -249,7 +249,7 @@ public class MongoUserProvider implements UserProvider { userModel.grantRole(realm.getRole(r)); } - for (ApplicationModel application : realm.getApplications()) { + for (ClientModel application : realm.getClients()) { for (String r : application.getDefaultRoles()) { userModel.grantRole(application.getRole(r)); } diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/OAuthClientAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/OAuthClientAdapter.java deleted file mode 100755 index 71b73ce9f1..0000000000 --- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/OAuthClientAdapter.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.keycloak.models.mongo.keycloak.adapters; - -import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext; -import org.keycloak.models.KeycloakSession; -import org.keycloak.models.OAuthClientModel; -import org.keycloak.models.RealmModel; -import org.keycloak.models.mongo.keycloak.entities.MongoOAuthClientEntity; - -/** - * @author Marek Posolda - */ -public class OAuthClientAdapter extends ClientAdapter implements OAuthClientModel { - - public OAuthClientAdapter(KeycloakSession session, RealmModel realm, MongoOAuthClientEntity oauthClientEntity, MongoStoreInvocationContext invContext) { - super(session, realm, oauthClientEntity, invContext); - } - - @Override - public void setClientId(String id) { - getMongoEntity().setName(id); - updateMongoEntity(); - } - - @Override - public boolean isDirectGrantsOnly() { - return getMongoEntity().isDirectGrantsOnly(); - } - - @Override - public void setDirectGrantsOnly(boolean flag) { - getMongoEntity().setDirectGrantsOnly(flag); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || !(o instanceof OAuthClientModel)) return false; - - OAuthClientModel that = (OAuthClientModel) o; - return that.getId().equals(getId()); - } - - @Override - public int hashCode() { - return getId().hashCode(); - } - -} diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java index eac95832a4..d7a534a9a5 100755 --- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java +++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java @@ -4,12 +4,10 @@ import com.mongodb.DBObject; import com.mongodb.QueryBuilder; import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext; import org.keycloak.enums.SslRequired; -import org.keycloak.models.ApplicationModel; import org.keycloak.models.ClientModel; import org.keycloak.models.IdentityProviderMapperModel; import org.keycloak.models.IdentityProviderModel; import org.keycloak.models.KeycloakSession; -import org.keycloak.models.OAuthClientModel; import org.keycloak.models.PasswordPolicy; import org.keycloak.models.RealmModel; import org.keycloak.models.RealmProvider; @@ -20,8 +18,7 @@ import org.keycloak.models.entities.IdentityProviderEntity; import org.keycloak.models.entities.IdentityProviderMapperEntity; import org.keycloak.models.entities.RequiredCredentialEntity; import org.keycloak.models.entities.UserFederationProviderEntity; -import org.keycloak.models.mongo.keycloak.entities.MongoApplicationEntity; -import org.keycloak.models.mongo.keycloak.entities.MongoOAuthClientEntity; +import org.keycloak.models.mongo.keycloak.entities.MongoClientEntity; import org.keycloak.models.mongo.keycloak.entities.MongoRealmEntity; import org.keycloak.models.mongo.keycloak.entities.MongoRoleEntity; import org.keycloak.models.utils.KeycloakModelUtils; @@ -579,80 +576,59 @@ public class RealmAdapter extends AbstractMongoAdapter impleme } @Override - public ClientModel findClient(String clientId) { - ClientModel model = getApplicationByName(clientId); - if (model != null) return model; - return getOAuthClient(clientId); + public ClientModel getClientById(String id) { + return model.getClientById(id, this); } @Override - public ClientModel findClientById(String id) { - ClientModel model = getApplicationById(id); - if (model != null) return model; - return getOAuthClientById(id); - } - - - - @Override - public ApplicationModel getApplicationById(String id) { - return model.getApplicationById(id, this); - } - - @Override - public ApplicationModel getApplicationByName(String name) { + public ClientModel getClientByClientId(String clientId) { DBObject query = new QueryBuilder() .and("realmId").is(getId()) - .and("name").is(name) + .and("clientId").is(clientId) .get(); - MongoApplicationEntity appEntity = getMongoStore().loadSingleEntity(MongoApplicationEntity.class, query, invocationContext); - return appEntity == null ? null : new ApplicationAdapter(session, this, appEntity, invocationContext); + MongoClientEntity appEntity = getMongoStore().loadSingleEntity(MongoClientEntity.class, query, invocationContext); + return appEntity == null ? null : new ClientAdapter(session, this, appEntity, invocationContext); } @Override - public Map getApplicationNameMap() { - Map resourceMap = new HashMap(); - for (ApplicationModel resource : getApplications()) { - resourceMap.put(resource.getName(), resource); + public Map getClientNameMap() { + Map resourceMap = new HashMap(); + for (ClientModel resource : getClients()) { + resourceMap.put(resource.getClientId(), resource); } return resourceMap; } @Override - public List getApplications() { + public List getClients() { DBObject query = new QueryBuilder() .and("realmId").is(getId()) .get(); - List appDatas = getMongoStore().loadEntities(MongoApplicationEntity.class, query, invocationContext); + List appDatas = getMongoStore().loadEntities(MongoClientEntity.class, query, invocationContext); - List result = new ArrayList(); - for (MongoApplicationEntity appData : appDatas) { - result.add(new ApplicationAdapter(session, this, appData, invocationContext)); + List result = new ArrayList(); + for (MongoClientEntity appData : appDatas) { + result.add(new ClientAdapter(session, this, appData, invocationContext)); } return result; } @Override - public ApplicationModel addApplication(String name) { - return this.addApplication(null, name); + public ClientModel addClient(String name) { + return this.addClient(null, name); } @Override - public ApplicationModel addApplication(String id, String name) { - MongoApplicationEntity appData = new MongoApplicationEntity(); + public ClientModel addClient(String id, String clientId) { + MongoClientEntity appData = new MongoClientEntity(); appData.setId(id); - appData.setName(name); + appData.setClientId(clientId); appData.setRealmId(getId()); appData.setEnabled(true); getMongoStore().insertEntity(appData, invocationContext); - final ApplicationModel model = new ApplicationAdapter(session, this, appData, invocationContext); - session.getKeycloakSessionFactory().publish(new ApplicationCreationEvent() { - @Override - public ApplicationModel getCreatedApplication() { - return model; - } - + final ClientModel model = new ClientAdapter(session, this, appData, invocationContext); + session.getKeycloakSessionFactory().publish(new ClientCreationEvent() { @Override public ClientModel getCreatedClient() { return model; @@ -662,69 +638,8 @@ public class RealmAdapter extends AbstractMongoAdapter impleme } @Override - public boolean removeApplication(String id) { - return getMongoStore().removeEntity(MongoApplicationEntity.class, id, invocationContext); - } - - @Override - public OAuthClientModel addOAuthClient(String name) { - return this.addOAuthClient(null, name); - } - - @Override - public OAuthClientModel addOAuthClient(String id, String name) { - MongoOAuthClientEntity oauthClient = new MongoOAuthClientEntity(); - oauthClient.setId(id); - oauthClient.setRealmId(getId()); - oauthClient.setName(name); - getMongoStore().insertEntity(oauthClient, invocationContext); - - final OAuthClientAdapter model = new OAuthClientAdapter(session, this, oauthClient, invocationContext); - session.getKeycloakSessionFactory().publish(new OAuthClientCreationEvent() { - @Override - public OAuthClientModel getCreatedOAuthClient() { - return model; - } - - @Override - public ClientModel getCreatedClient() { - return model; - } - }); - return model; - } - - @Override - public boolean removeOAuthClient(String id) { - return getMongoStore().removeEntity(MongoOAuthClientEntity.class, id, invocationContext); - } - - @Override - public OAuthClientModel getOAuthClient(String name) { - DBObject query = new QueryBuilder() - .and("realmId").is(getId()) - .and("name").is(name) - .get(); - MongoOAuthClientEntity oauthClient = getMongoStore().loadSingleEntity(MongoOAuthClientEntity.class, query, invocationContext); - return oauthClient == null ? null : new OAuthClientAdapter(session, this, oauthClient, invocationContext); - } - - @Override - public OAuthClientModel getOAuthClientById(String id) { - return model.getOAuthClientById(id, this); - } - - @Override - public List getOAuthClients() { - DBObject query = new QueryBuilder() - .and("realmId").is(getId()) - .get(); - List results = getMongoStore().loadEntities(MongoOAuthClientEntity.class, query, invocationContext); - List list = new ArrayList(); - for (MongoOAuthClientEntity data : results) { - list.add(new OAuthClientAdapter(session, this, data, invocationContext)); - } - return list; + public boolean removeClient(String id) { + return getMongoStore().removeEntity(MongoClientEntity.class, id, invocationContext); } @Override @@ -1063,14 +978,14 @@ public class RealmAdapter extends AbstractMongoAdapter impleme } @Override - public ApplicationModel getMasterAdminApp() { - MongoApplicationEntity appData = getMongoStore().loadEntity(MongoApplicationEntity.class, realm.getAdminAppId(), invocationContext); - return appData != null ? new ApplicationAdapter(session, this, appData, invocationContext) : null; + public ClientModel getMasterAdminClient() { + MongoClientEntity appData = getMongoStore().loadEntity(MongoClientEntity.class, realm.getAdminAppId(), invocationContext); + return appData != null ? new ClientAdapter(session, this, appData, invocationContext) : null; } @Override - public void setMasterAdminApp(ApplicationModel app) { - String adminAppId = app != null ? app.getId() : null; + public void setMasterAdminClient(ClientModel client) { + String adminAppId = client != null ? client.getId() : null; realm.setAdminAppId(adminAppId); updateRealm(); } diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RoleAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RoleAdapter.java index c2a831734d..91ef361da2 100755 --- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RoleAdapter.java +++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RoleAdapter.java @@ -7,7 +7,7 @@ import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; import org.keycloak.models.RoleContainerModel; import org.keycloak.models.RoleModel; -import org.keycloak.models.mongo.keycloak.entities.MongoApplicationEntity; +import org.keycloak.models.mongo.keycloak.entities.MongoClientEntity; import org.keycloak.models.mongo.keycloak.entities.MongoRealmEntity; import org.keycloak.models.mongo.keycloak.entities.MongoRoleEntity; import org.keycloak.models.utils.KeycloakModelUtils; @@ -115,14 +115,14 @@ public class RoleAdapter extends AbstractMongoAdapter implement throw new IllegalStateException("Realm with id: " + role.getRealmId() + " doesn't exists"); } roleContainer = new RealmAdapter(session, realm, invocationContext); - } else if (role.getApplicationId() != null) { - MongoApplicationEntity appEntity = getMongoStore().loadEntity(MongoApplicationEntity.class, role.getApplicationId(), invocationContext); + } else if (role.getClientId() != null) { + MongoClientEntity appEntity = getMongoStore().loadEntity(MongoClientEntity.class, role.getClientId(), invocationContext); if (appEntity == null) { - throw new IllegalStateException("Application with id: " + role.getApplicationId() + " doesn't exists"); + throw new IllegalStateException("Application with id: " + role.getClientId() + " doesn't exists"); } - roleContainer = new ApplicationAdapter(session, realm, appEntity, invocationContext); + roleContainer = new ClientAdapter(session, realm, appEntity, invocationContext); } else { - throw new IllegalStateException("Both realmId and applicationId are null for role: " + this); + throw new IllegalStateException("Both realmId and clientId are null for role: " + this); } } return roleContainer; diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/UserAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/UserAdapter.java index da26379f14..874f7d8159 100755 --- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/UserAdapter.java +++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/UserAdapter.java @@ -1,7 +1,7 @@ package org.keycloak.models.mongo.keycloak.adapters; import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext; -import org.keycloak.models.ApplicationModel; +import org.keycloak.models.ClientModel; import org.keycloak.models.KeycloakSession; import org.keycloak.models.PasswordPolicy; import org.keycloak.models.RealmModel; @@ -316,12 +316,12 @@ public class UserAdapter extends AbstractMongoAdapter implement } @Override - public Set getApplicationRoleMappings(ApplicationModel app) { + public Set getClientRoleMappings(ClientModel app) { Set result = new HashSet(); List roles = MongoModelUtils.getAllRolesOfUser(this, invocationContext); for (MongoRoleEntity role : roles) { - if (app.getId().equals(role.getApplicationId())) { + if (app.getId().equals(role.getClientId())) { result.add(new RoleAdapter(session, realm, role, app, invocationContext)); } } diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoApplicationEntity.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoClientEntity.java similarity index 71% rename from model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoApplicationEntity.java rename to model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoClientEntity.java index 7534e66fb0..cc97d5d992 100755 --- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoApplicationEntity.java +++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoClientEntity.java @@ -5,19 +5,19 @@ import com.mongodb.QueryBuilder; import org.keycloak.connections.mongo.api.MongoCollection; import org.keycloak.connections.mongo.api.MongoIdentifiableEntity; import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext; -import org.keycloak.models.entities.ApplicationEntity; +import org.keycloak.models.entities.ClientEntity; /** * @author Marek Posolda */ -@MongoCollection(collectionName = "applications") -public class MongoApplicationEntity extends ApplicationEntity implements MongoIdentifiableEntity { +@MongoCollection(collectionName = "clients") +public class MongoClientEntity extends ClientEntity implements MongoIdentifiableEntity { @Override public void afterRemove(MongoStoreInvocationContext context) { // Remove all roles, which belongs to this application DBObject query = new QueryBuilder() - .and("applicationId").is(getId()) + .and("clientId").is(getId()) .get(); context.getMongoStore().removeEntities(MongoRoleEntity.class, query, context); } diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoOAuthClientEntity.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoOAuthClientEntity.java deleted file mode 100755 index ab01359cd5..0000000000 --- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoOAuthClientEntity.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.keycloak.models.mongo.keycloak.entities; - -import com.mongodb.DBObject; -import com.mongodb.QueryBuilder; -import org.keycloak.connections.mongo.api.MongoCollection; -import org.keycloak.connections.mongo.api.MongoIdentifiableEntity; -import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext; -import org.keycloak.models.entities.OAuthClientEntity; - -/** - * @author Marek Posolda - */ -@MongoCollection(collectionName = "oauthClients") -public class MongoOAuthClientEntity extends OAuthClientEntity implements MongoIdentifiableEntity { - - @Override - public void afterRemove(MongoStoreInvocationContext context) { - // Remove all session associations - DBObject query = new QueryBuilder() - .and("associatedClientIds").is(getId()) - .get(); - } -} diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoRealmEntity.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoRealmEntity.java index 278435200c..22097514fb 100755 --- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoRealmEntity.java +++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoRealmEntity.java @@ -26,9 +26,6 @@ public class MongoRealmEntity extends RealmEntity implements MongoIdentifiableEn context.getMongoStore().removeEntities(MongoRoleEntity.class, query, context); // Remove all applications of this realm - context.getMongoStore().removeEntities(MongoApplicationEntity.class, query, context); - - // Remove all clients of this realm - context.getMongoStore().removeEntities(MongoOAuthClientEntity.class, query, context); + context.getMongoStore().removeEntities(MongoClientEntity.class, query, context); } } diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoRoleEntity.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoRoleEntity.java index 4b4e80f861..dc820c25f8 100755 --- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoRoleEntity.java +++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoRoleEntity.java @@ -24,13 +24,13 @@ public class MongoRoleEntity extends RoleEntity implements MongoIdentifiableEnti // TODO This is required as Mongo doesn't support sparse indexes with compound keys (see https://jira.mongodb.org/browse/SERVER-2193) public String getNameIndex() { String realmId = getRealmId(); - String applicationId = getApplicationId(); + String clientId = getClientId(); String name = getName(); if (realmId != null) { return realmId + "//" + name; } else { - return applicationId + "//" + name; + return clientId + "//" + name; } } @@ -74,8 +74,8 @@ public class MongoRoleEntity extends RoleEntity implements MongoIdentifiableEnti } // Remove defaultRoles from application - if (getApplicationId() != null) { - MongoApplicationEntity appEntity = mongoStore.loadEntity(MongoApplicationEntity.class, getApplicationId(), invContext); + if (getClientId() != null) { + MongoClientEntity appEntity = mongoStore.loadEntity(MongoClientEntity.class, getClientId(), invContext); // Application might be already removed at this point if (appEntity != null) { diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/utils/MongoModelUtils.java b/model/mongo/src/main/java/org/keycloak/models/mongo/utils/MongoModelUtils.java index 63f0bfdaa2..48828deecb 100755 --- a/model/mongo/src/main/java/org/keycloak/models/mongo/utils/MongoModelUtils.java +++ b/model/mongo/src/main/java/org/keycloak/models/mongo/utils/MongoModelUtils.java @@ -36,7 +36,7 @@ public class MongoModelUtils { // Get everything including both application and realm scopes public static List getAllScopesOfClient(ClientModel client, MongoStoreInvocationContext invContext) { - ClientEntity scopedEntity = ((ClientAdapter)client).getMongoEntityAsClient(); + ClientEntity scopedEntity = ((ClientAdapter)client).getMongoEntity(); List scopeIds = scopedEntity.getScopeIds(); if (scopeIds == null || scopeIds.isEmpty()) { diff --git a/model/sessions-infinispan/src/main/java/org/keycloak/models/sessions/infinispan/ClientSessionAdapter.java b/model/sessions-infinispan/src/main/java/org/keycloak/models/sessions/infinispan/ClientSessionAdapter.java index 645a76f47a..e380441885 100644 --- a/model/sessions-infinispan/src/main/java/org/keycloak/models/sessions/infinispan/ClientSessionAdapter.java +++ b/model/sessions-infinispan/src/main/java/org/keycloak/models/sessions/infinispan/ClientSessionAdapter.java @@ -43,7 +43,7 @@ public class ClientSessionAdapter implements ClientSessionModel { @Override public ClientModel getClient() { - return realm.findClientById(entity.getClient()); + return realm.getClientById(entity.getClient()); } @Override diff --git a/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/ClientSessionAdapter.java b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/ClientSessionAdapter.java index 18b0332ef1..ebb47b698a 100755 --- a/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/ClientSessionAdapter.java +++ b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/ClientSessionAdapter.java @@ -82,7 +82,7 @@ public class ClientSessionAdapter implements ClientSessionModel { @Override public ClientModel getClient() { - return realm.findClientById(entity.getClientId()); + return realm.getClientById(entity.getClientId()); } @Override diff --git a/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/JpaUserSessionProvider.java b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/JpaUserSessionProvider.java index d70c3263fb..0731de33a8 100755 --- a/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/JpaUserSessionProvider.java +++ b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/JpaUserSessionProvider.java @@ -20,7 +20,6 @@ import javax.persistence.EntityManager; import javax.persistence.TypedQuery; import java.util.LinkedList; import java.util.List; -import java.util.Map; /** * @author Stian Thorgersen diff --git a/model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/ClientSessionAdapter.java b/model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/ClientSessionAdapter.java index 9981fb7634..62a3246bcd 100755 --- a/model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/ClientSessionAdapter.java +++ b/model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/ClientSessionAdapter.java @@ -41,7 +41,7 @@ public class ClientSessionAdapter implements ClientSessionModel { @Override public ClientModel getClient() { - return realm.findClientById(entity.getClientId()); + return realm.getClientById(entity.getClientId()); } @Override diff --git a/model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/MemUserSessionProvider.java b/model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/MemUserSessionProvider.java index c185a0b05c..67a218014f 100755 --- a/model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/MemUserSessionProvider.java +++ b/model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/MemUserSessionProvider.java @@ -25,7 +25,6 @@ import java.util.LinkedList; import java.util.List; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.CopyOnWriteArraySet; /** * @author Stian Thorgersen diff --git a/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/ClientSessionAdapter.java b/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/ClientSessionAdapter.java index 2ab8630bc4..12efd4a368 100755 --- a/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/ClientSessionAdapter.java +++ b/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/ClientSessionAdapter.java @@ -44,7 +44,7 @@ public class ClientSessionAdapter extends AbstractMongoAdapter - - - keycloak-picketlink-parent - org.keycloak - 1.2.0.RC1-SNAPSHOT - ../pom.xml - - 4.0.0 - - keycloak-picketlink-api - Keycloak Picketlink API - - - - - org.keycloak - keycloak-core - ${project.version} - provided - - - org.keycloak - keycloak-model-api - ${project.version} - provided - - - org.picketlink - picketlink-idm-api - provided - - - org.jboss.logging - jboss-logging - provided - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - ${maven.compiler.source} - ${maven.compiler.target} - - - - - - diff --git a/picketlink/keycloak-picketlink-api/src/main/java/org/keycloak/picketlink/PartitionManagerProvider.java b/picketlink/keycloak-picketlink-api/src/main/java/org/keycloak/picketlink/PartitionManagerProvider.java deleted file mode 100644 index 0b22305364..0000000000 --- a/picketlink/keycloak-picketlink-api/src/main/java/org/keycloak/picketlink/PartitionManagerProvider.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.keycloak.picketlink; - -import org.keycloak.models.UserFederationProviderModel; -import org.keycloak.provider.Provider; -import org.picketlink.idm.PartitionManager; - -/** - * - * @author Marek Posolda - */ -public interface PartitionManagerProvider extends Provider { - - PartitionManager getPartitionManager(UserFederationProviderModel model); -} diff --git a/picketlink/keycloak-picketlink-api/src/main/java/org/keycloak/picketlink/PartitionManagerProviderFactory.java b/picketlink/keycloak-picketlink-api/src/main/java/org/keycloak/picketlink/PartitionManagerProviderFactory.java deleted file mode 100644 index 203c7f9c23..0000000000 --- a/picketlink/keycloak-picketlink-api/src/main/java/org/keycloak/picketlink/PartitionManagerProviderFactory.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.keycloak.picketlink; - -import org.keycloak.provider.ProviderFactory; - -/** - * @author Marek Posolda - */ -public interface PartitionManagerProviderFactory extends ProviderFactory { -} diff --git a/picketlink/keycloak-picketlink-api/src/main/java/org/keycloak/picketlink/PartitionManagerSpi.java b/picketlink/keycloak-picketlink-api/src/main/java/org/keycloak/picketlink/PartitionManagerSpi.java deleted file mode 100644 index 721cf12d68..0000000000 --- a/picketlink/keycloak-picketlink-api/src/main/java/org/keycloak/picketlink/PartitionManagerSpi.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.keycloak.picketlink; - -import org.keycloak.provider.Provider; -import org.keycloak.provider.ProviderFactory; -import org.keycloak.provider.Spi; - -/** - * @author Stian Thorgersen - */ -public class PartitionManagerSpi implements Spi { - @Override - public String getName() { - return "picketlink-idm"; - } - - @Override - public Class getProviderClass() { - return PartitionManagerProvider.class; - } - - @Override - public Class getProviderFactoryClass() { - return PartitionManagerProviderFactory.class; - } -} diff --git a/picketlink/keycloak-picketlink-api/src/main/resources/META-INF/services/org.keycloak.provider.Spi b/picketlink/keycloak-picketlink-api/src/main/resources/META-INF/services/org.keycloak.provider.Spi deleted file mode 100644 index 88b1bcc076..0000000000 --- a/picketlink/keycloak-picketlink-api/src/main/resources/META-INF/services/org.keycloak.provider.Spi +++ /dev/null @@ -1 +0,0 @@ -org.keycloak.picketlink.PartitionManagerSpi \ No newline at end of file diff --git a/picketlink/keycloak-picketlink-ldap/pom.xml b/picketlink/keycloak-picketlink-ldap/pom.xml deleted file mode 100755 index 921637699d..0000000000 --- a/picketlink/keycloak-picketlink-ldap/pom.xml +++ /dev/null @@ -1,66 +0,0 @@ - - - - keycloak-picketlink-parent - org.keycloak - 1.2.0.RC1-SNAPSHOT - ../pom.xml - - 4.0.0 - - keycloak-picketlink-ldap - Keycloak Picketlink LDAP - - - - - org.keycloak - keycloak-core - ${project.version} - provided - - - org.keycloak - keycloak-model-api - ${project.version} - provided - - - org.keycloak - keycloak-picketlink-api - ${project.version} - provided - - - org.picketlink - picketlink-idm-api - provided - - - org.picketlink - picketlink-idm-impl - provided - - - org.jboss.logging - jboss-logging - provided - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - ${maven.compiler.source} - ${maven.compiler.target} - - - - - - diff --git a/picketlink/keycloak-picketlink-ldap/src/main/java/org/keycloak/picketlink/idm/KeycloakEventBridge.java b/picketlink/keycloak-picketlink-ldap/src/main/java/org/keycloak/picketlink/idm/KeycloakEventBridge.java deleted file mode 100755 index 1fd7f159d8..0000000000 --- a/picketlink/keycloak-picketlink-ldap/src/main/java/org/keycloak/picketlink/idm/KeycloakEventBridge.java +++ /dev/null @@ -1,63 +0,0 @@ -package org.keycloak.picketlink.idm; - -import org.jboss.logging.Logger; -import org.picketlink.idm.IdentityManager; -import org.picketlink.idm.PartitionManager; -import org.picketlink.idm.event.CredentialUpdatedEvent; -import org.picketlink.idm.event.EventBridge; -import org.picketlink.idm.internal.ContextualIdentityManager; -import org.picketlink.idm.ldap.internal.LDAPIdentityStore; -import org.picketlink.idm.ldap.internal.LDAPOperationManager; -import org.picketlink.idm.model.basic.User; -import org.picketlink.idm.spi.CredentialStore; -import org.picketlink.idm.spi.IdentityContext; -import org.picketlink.idm.spi.StoreSelector; - -import javax.naming.directory.BasicAttribute; -import javax.naming.directory.DirContext; -import javax.naming.directory.ModificationItem; - -/** - * @author Marek Posolda - */ -public class KeycloakEventBridge implements EventBridge { - - private static final Logger logger = Logger.getLogger(KeycloakEventBridge.class); - - private final boolean updateUserAccountAfterPasswordUpdate; - - public KeycloakEventBridge(boolean updateUserAccountAfterPasswordUpdate) { - this.updateUserAccountAfterPasswordUpdate = updateUserAccountAfterPasswordUpdate; - if (updateUserAccountAfterPasswordUpdate) { - logger.info("userAccountControl attribute will be updated in Active Directory after user registration"); - } - } - - @Override - public void raiseEvent(Object event) { - // Used in ActiveDirectory to put account into "enabled" state (aka userAccountControl=512, see http://support.microsoft.com/kb/305144/en ) after password update. If value is -1, it's ignored - if (updateUserAccountAfterPasswordUpdate && event instanceof CredentialUpdatedEvent) { - CredentialUpdatedEvent credEvent = ((CredentialUpdatedEvent) event); - PartitionManager partitionManager = credEvent.getPartitionMananger(); - ContextualIdentityManager identityManager = (ContextualIdentityManager) partitionManager.createIdentityManager(); - IdentityContext identityCtx = identityManager.getIdentityContext(); - - CredentialStore store = identityManager.getStoreSelector().getStoreForCredentialOperation(identityCtx, credEvent.getCredential().getClass()); - if (store instanceof LDAPIdentityStore) { - LDAPIdentityStore ldapStore = (LDAPIdentityStore)store; - LDAPOperationManager operationManager = ldapStore.getOperationManager(); - User picketlinkUser = (User) credEvent.getAccount(); - String userDN = ldapStore.getBindingDN(picketlinkUser, true); - - ModificationItem[] mods = new ModificationItem[1]; - BasicAttribute mod0 = new BasicAttribute("userAccountControl", "512"); - mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, mod0); - operationManager.modifyAttribute(userDN, mod0); - logger.debug("Attribute userAccountControls switched to 512 after password update of user " + picketlinkUser.getLoginName()); - } else { - logger.debug("Store for credential updates is not LDAPIdentityStore. Ignored"); - } - - } - } -} diff --git a/picketlink/keycloak-picketlink-ldap/src/main/java/org/keycloak/picketlink/idm/LDAPKeycloakCredentialHandler.java b/picketlink/keycloak-picketlink-ldap/src/main/java/org/keycloak/picketlink/idm/LDAPKeycloakCredentialHandler.java deleted file mode 100755 index bc5278c316..0000000000 --- a/picketlink/keycloak-picketlink-ldap/src/main/java/org/keycloak/picketlink/idm/LDAPKeycloakCredentialHandler.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.keycloak.picketlink.idm; - -import org.picketlink.idm.IdentityManager; -import org.picketlink.idm.config.LDAPMappingConfiguration; -import org.picketlink.idm.credential.UsernamePasswordCredentials; -import org.picketlink.idm.credential.storage.CredentialStorage; -import org.picketlink.idm.ldap.internal.LDAPIdentityStore; -import org.picketlink.idm.ldap.internal.LDAPPlainTextPasswordCredentialHandler; -import org.picketlink.idm.model.Account; -import org.picketlink.idm.model.basic.BasicModel; -import org.picketlink.idm.model.basic.User; -import org.picketlink.idm.spi.IdentityContext; - -import javax.naming.directory.SearchResult; - -import static org.picketlink.idm.IDMLog.CREDENTIAL_LOGGER; - -/** - * @author Marek Posolda - */ -public class LDAPKeycloakCredentialHandler extends LDAPPlainTextPasswordCredentialHandler { - - // Overridden as in Keycloak, we don't have Agents - @Override - protected User getAccount(IdentityContext context, String loginName) { - IdentityManager identityManager = getIdentityManager(context); - - if (CREDENTIAL_LOGGER.isDebugEnabled()) { - CREDENTIAL_LOGGER.debugf("Trying to find account [%s] using default account type [%s]", loginName, User.class); - } - - return BasicModel.getUser(identityManager, loginName); - } - - - @Override - protected boolean validateCredential(IdentityContext context, CredentialStorage credentialStorage, UsernamePasswordCredentials credentials, LDAPIdentityStore ldapIdentityStore) { - Account account = getAccount(context, credentials.getUsername()); - char[] password = credentials.getPassword().getValue(); - String userDN = (String) account.getAttribute(LDAPIdentityStore.ENTRY_DN_ATTRIBUTE_NAME).getValue(); - if (CREDENTIAL_LOGGER.isDebugEnabled()) { - CREDENTIAL_LOGGER.debugf("Using DN [%s] for authentication of user [%s]", userDN, credentials.getUsername()); - } - - if (ldapIdentityStore.getOperationManager().authenticate(userDN, new String(password))) { - return true; - } - - return false; - } -} diff --git a/picketlink/keycloak-picketlink-ldap/src/main/java/org/keycloak/picketlink/ldap/LDAPPartitionManagerProvider.java b/picketlink/keycloak-picketlink-ldap/src/main/java/org/keycloak/picketlink/ldap/LDAPPartitionManagerProvider.java deleted file mode 100644 index bbb7201e69..0000000000 --- a/picketlink/keycloak-picketlink-ldap/src/main/java/org/keycloak/picketlink/ldap/LDAPPartitionManagerProvider.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.keycloak.picketlink.ldap; - -import org.keycloak.models.UserFederationProviderModel; -import org.keycloak.picketlink.PartitionManagerProvider; -import org.picketlink.idm.PartitionManager; - -/** - * @author Marek Posolda - */ -public class LDAPPartitionManagerProvider implements PartitionManagerProvider { - - private final PartitionManagerRegistry partitionManagerRegistry; - - public LDAPPartitionManagerProvider(PartitionManagerRegistry partitionManagerRegistry) { - this.partitionManagerRegistry = partitionManagerRegistry; - } - - @Override - public PartitionManager getPartitionManager(UserFederationProviderModel model) { - return partitionManagerRegistry.getPartitionManager(model); - } - - @Override - public void close() { - } -} diff --git a/picketlink/keycloak-picketlink-ldap/src/main/java/org/keycloak/picketlink/ldap/LDAPPartitionManagerProviderFactory.java b/picketlink/keycloak-picketlink-ldap/src/main/java/org/keycloak/picketlink/ldap/LDAPPartitionManagerProviderFactory.java deleted file mode 100755 index 851201d8f0..0000000000 --- a/picketlink/keycloak-picketlink-ldap/src/main/java/org/keycloak/picketlink/ldap/LDAPPartitionManagerProviderFactory.java +++ /dev/null @@ -1,43 +0,0 @@ -package org.keycloak.picketlink.ldap; - -import org.keycloak.Config; -import org.keycloak.models.KeycloakSession; -import org.keycloak.models.KeycloakSessionFactory; -import org.keycloak.picketlink.PartitionManagerProvider; -import org.keycloak.picketlink.PartitionManagerProviderFactory; -import org.picketlink.idm.PartitionManager; - -/** - * Obtains {@link PartitionManager} instances from shared {@link PartitionManagerRegistry} and uses UserFederationModel configuration for it - * - * @author Marek Posolda - */ -public class LDAPPartitionManagerProviderFactory implements PartitionManagerProviderFactory { - - private PartitionManagerRegistry partitionManagerRegistry; - - @Override - public PartitionManagerProvider create(KeycloakSession session) { - return new LDAPPartitionManagerProvider(partitionManagerRegistry); - } - - @Override - public void init(Config.Scope config) { - partitionManagerRegistry = new PartitionManagerRegistry(); - } - - @Override - public void postInit(KeycloakSessionFactory factory) { - - } - - @Override - public void close() { - } - - @Override - public String getId() { - return "ldap"; - } - -} diff --git a/picketlink/keycloak-picketlink-ldap/src/main/java/org/keycloak/picketlink/ldap/PartitionManagerRegistry.java b/picketlink/keycloak-picketlink-ldap/src/main/java/org/keycloak/picketlink/ldap/PartitionManagerRegistry.java deleted file mode 100755 index a120ee1876..0000000000 --- a/picketlink/keycloak-picketlink-ldap/src/main/java/org/keycloak/picketlink/ldap/PartitionManagerRegistry.java +++ /dev/null @@ -1,163 +0,0 @@ -package org.keycloak.picketlink.ldap; - -import org.jboss.logging.Logger; -import org.keycloak.models.LDAPConstants; -import org.keycloak.models.UserFederationProviderModel; -import org.keycloak.picketlink.idm.KeycloakEventBridge; -import org.keycloak.picketlink.idm.LDAPKeycloakCredentialHandler; -import org.picketlink.idm.PartitionManager; -import org.picketlink.idm.config.IdentityConfigurationBuilder; -import org.picketlink.idm.config.LDAPMappingConfigurationBuilder; -import org.picketlink.idm.config.LDAPStoreConfigurationBuilder; -import org.picketlink.idm.internal.DefaultPartitionManager; -import org.picketlink.idm.model.basic.User; - -import java.util.HashMap; -import java.util.Map; -import java.util.Properties; -import java.util.concurrent.ConcurrentHashMap; - -import static org.picketlink.common.constants.LDAPConstants.*; - -/** - * @author Marek Posolda - */ -public class PartitionManagerRegistry { - - private static final Logger logger = Logger.getLogger(PartitionManagerRegistry.class); - - private Map partitionManagers = new ConcurrentHashMap(); - - public PartitionManager getPartitionManager(UserFederationProviderModel model) { - PartitionManagerContext context = partitionManagers.get(model.getId()); - - // Ldap config might have changed for the realm. In this case, we must re-initialize - Map config = model.getConfig(); - if (context == null || !config.equals(context.config)) { - logLDAPConfig(model.getId(), config); - - PartitionManager manager = createPartitionManager(config); - context = new PartitionManagerContext(config, manager); - partitionManagers.put(model.getId(), context); - } - return context.partitionManager; - } - - // Don't log LDAP password - private void logLDAPConfig(String fedProviderId, Map ldapConfig) { - Map copy = new HashMap(ldapConfig); - copy.remove(LDAPConstants.BIND_CREDENTIAL); - logger.infof("Creating new LDAP based partition manager for the Federation provider: " + fedProviderId + ", LDAP Configuration: " + copy); - } - - /** - * @param ldapConfig from realm - * @return PartitionManager instance based on LDAP store - */ - public static PartitionManager createPartitionManager(Map ldapConfig) { - IdentityConfigurationBuilder builder = new IdentityConfigurationBuilder(); - - Properties connectionProps = new Properties(); - if (ldapConfig.containsKey(LDAPConstants.CONNECTION_POOLING)) { - connectionProps.put("com.sun.jndi.ldap.connect.pool", ldapConfig.get(LDAPConstants.CONNECTION_POOLING)); - } - - checkSystemProperty("com.sun.jndi.ldap.connect.pool.authentication", "none simple"); - checkSystemProperty("com.sun.jndi.ldap.connect.pool.initsize", "1"); - checkSystemProperty("com.sun.jndi.ldap.connect.pool.maxsize", "1000"); - checkSystemProperty("com.sun.jndi.ldap.connect.pool.prefsize", "5"); - checkSystemProperty("com.sun.jndi.ldap.connect.pool.timeout", "300000"); - checkSystemProperty("com.sun.jndi.ldap.connect.pool.protocol", "plain"); - checkSystemProperty("com.sun.jndi.ldap.connect.pool.debug", "off"); - - String vendor = ldapConfig.get(LDAPConstants.VENDOR); - - boolean activeDirectory = vendor != null && vendor.equals(LDAPConstants.VENDOR_ACTIVE_DIRECTORY); - - String ldapLoginNameMapping = ldapConfig.get(LDAPConstants.USERNAME_LDAP_ATTRIBUTE); - if (ldapLoginNameMapping == null) { - ldapLoginNameMapping = activeDirectory ? CN : UID; - } - - String ldapFirstNameMapping = activeDirectory ? "givenName" : CN; - String createTimestampMapping = activeDirectory ? "whenCreated" : CREATE_TIMESTAMP; - String modifyTimestampMapping = activeDirectory ? "whenChanged" : MODIFY_TIMESTAMP; - String[] userObjectClasses = getUserObjectClasses(ldapConfig); - - boolean pagination = ldapConfig.containsKey(LDAPConstants.PAGINATION) ? Boolean.parseBoolean(ldapConfig.get(LDAPConstants.PAGINATION)) : false; - - // Use same mapping for User and Agent for now - LDAPStoreConfigurationBuilder ldapStoreBuilder = - builder - .named("SIMPLE_LDAP_STORE_CONFIG") - .stores() - .ldap() - .connectionProperties(connectionProps) - .addCredentialHandler(LDAPKeycloakCredentialHandler.class) - .baseDN(ldapConfig.get(LDAPConstants.BASE_DN)) - .bindDN(ldapConfig.get(LDAPConstants.BIND_DN)) - .bindCredential(ldapConfig.get(LDAPConstants.BIND_CREDENTIAL)) - .url(ldapConfig.get(LDAPConstants.CONNECTION_URL)) - .activeDirectory(activeDirectory) - .supportAllFeatures() - .pagination(pagination); - - // RHDS is using "nsuniqueid" as unique identifier instead of "entryUUID" - if (vendor != null && vendor.equals(LDAPConstants.VENDOR_RHDS)) { - ldapStoreBuilder.uniqueIdentifierAttributeName("nsuniqueid"); - } else if (LDAPConstants.VENDOR_TIVOLI.equals(vendor)) { - ldapStoreBuilder.uniqueIdentifierAttributeName("uniqueidentifier"); - } - - LDAPMappingConfigurationBuilder ldapUserMappingBuilder = ldapStoreBuilder - .mapping(User.class) - .baseDN(ldapConfig.get(LDAPConstants.USER_DN_SUFFIX)) - .objectClasses(userObjectClasses) - .attribute("loginName", ldapLoginNameMapping, true) - .attribute("firstName", ldapFirstNameMapping) - .attribute("lastName", SN) - .attribute("email", EMAIL) - .readOnlyAttribute("createdDate", createTimestampMapping) - .readOnlyAttribute("modifyDate", modifyTimestampMapping); - - if (activeDirectory && ldapLoginNameMapping.equals("sAMAccountName")) { - ldapUserMappingBuilder.bindingAttribute("fullName", CN); - logger.infof("Using 'cn' attribute for DN of user and 'sAMAccountName' for username"); - } - - KeycloakEventBridge eventBridge = new KeycloakEventBridge(activeDirectory && "true".equals(ldapConfig.get(LDAPConstants.USER_ACCOUNT_CONTROLS_AFTER_PASSWORD_UPDATE))); - return new DefaultPartitionManager(builder.buildAll(), eventBridge, null); - } - - private static void checkSystemProperty(String name, String defaultValue) { - if (System.getProperty(name) == null) { - System.setProperty(name, defaultValue); - } - } - - // Parse array of strings like [ "inetOrgPerson", "organizationalPerson" ] from the string like: "inetOrgPerson, organizationalPerson" - private static String[] getUserObjectClasses(Map ldapConfig) { - String objClassesCfg = ldapConfig.get(LDAPConstants.USER_OBJECT_CLASSES); - String objClassesStr = (objClassesCfg != null && objClassesCfg.length() > 0) ? objClassesCfg.trim() : "inetOrgPerson, organizationalPerson"; - - String[] objectClasses = objClassesStr.split(","); - - // Trim them - String[] userObjectClasses = new String[objectClasses.length]; - for (int i=0 ; i config, PartitionManager manager) { - this.config = config; - this.partitionManager = manager; - } - - private Map config; - private PartitionManager partitionManager; - } -} diff --git a/picketlink/keycloak-picketlink-ldap/src/main/resources/META-INF/services/org.keycloak.picketlink.PartitionManagerProviderFactory b/picketlink/keycloak-picketlink-ldap/src/main/resources/META-INF/services/org.keycloak.picketlink.PartitionManagerProviderFactory deleted file mode 100644 index 5bfaf9d173..0000000000 --- a/picketlink/keycloak-picketlink-ldap/src/main/resources/META-INF/services/org.keycloak.picketlink.PartitionManagerProviderFactory +++ /dev/null @@ -1 +0,0 @@ -org.keycloak.picketlink.ldap.LDAPPartitionManagerProviderFactory \ No newline at end of file diff --git a/picketlink/pom.xml b/picketlink/pom.xml deleted file mode 100755 index 10f193561d..0000000000 --- a/picketlink/pom.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - keycloak-parent - org.keycloak - 1.2.0.RC1-SNAPSHOT - ../pom.xml - - 4.0.0 - pom - - keycloak-picketlink-parent - Keycloak Picketlink - - - - keycloak-picketlink-api - keycloak-picketlink-ldap - - - - diff --git a/pom.xml b/pom.xml index f3f68b0414..87ac6079b2 100755 --- a/pom.xml +++ b/pom.xml @@ -114,7 +114,6 @@ model integration proxy - picketlink federation services saml diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/EntityDescriptorImporter.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/EntityDescriptorImporter.java index 32f0990d6c..1ad72bfd39 100755 --- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/EntityDescriptorImporter.java +++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/EntityDescriptorImporter.java @@ -1,6 +1,6 @@ package org.keycloak.protocol.saml; -import org.keycloak.exportimport.ApplicationImporter; +import org.keycloak.exportimport.ClientImporter; import org.keycloak.models.RealmModel; import org.keycloak.services.resources.admin.RealmAuth; @@ -8,7 +8,7 @@ import org.keycloak.services.resources.admin.RealmAuth; * @author Bill Burke * @version $Revision: 1 $ */ -public class EntityDescriptorImporter implements ApplicationImporter { +public class EntityDescriptorImporter implements ClientImporter { @Override public Object createJaxrsService(RealmModel realm, RealmAuth auth) { return new EntityDescriptorImporterService(realm, auth); diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/EntityDescriptorImporterFactory.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/EntityDescriptorImporterFactory.java index 51644d904a..14af68569d 100755 --- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/EntityDescriptorImporterFactory.java +++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/EntityDescriptorImporterFactory.java @@ -1,8 +1,8 @@ package org.keycloak.protocol.saml; import org.keycloak.Config; -import org.keycloak.exportimport.ApplicationImporter; -import org.keycloak.exportimport.ApplicationImporterFactory; +import org.keycloak.exportimport.ClientImporter; +import org.keycloak.exportimport.ClientImporterFactory; import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSessionFactory; @@ -10,14 +10,14 @@ import org.keycloak.models.KeycloakSessionFactory; * @author Bill Burke * @version $Revision: 1 $ */ -public class EntityDescriptorImporterFactory implements ApplicationImporterFactory { +public class EntityDescriptorImporterFactory implements ClientImporterFactory { @Override public String getDisplayName() { return "SAML 2.0 Entity Descriptor"; } @Override - public ApplicationImporter create(KeycloakSession session) { + public ClientImporter create(KeycloakSession session) { return new EntityDescriptorImporter(); } diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/EntityDescriptorImporterService.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/EntityDescriptorImporterService.java index 68a7412eee..4ef05eaaa5 100755 --- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/EntityDescriptorImporterService.java +++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/EntityDescriptorImporterService.java @@ -2,7 +2,7 @@ package org.keycloak.protocol.saml; import org.jboss.resteasy.plugins.providers.multipart.InputPart; import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataInput; -import org.keycloak.models.ApplicationModel; +import org.keycloak.models.ClientModel; import org.keycloak.models.RealmModel; import org.keycloak.models.utils.KeycloakModelUtils; import org.keycloak.services.resources.admin.RealmAuth; @@ -79,7 +79,7 @@ public class EntityDescriptorImporterService { for (Object o : entities.getEntityDescriptor()) { EntityDescriptorType entity = (EntityDescriptorType)o; String entityId = entity.getEntityID(); - ApplicationModel app = realm.addApplication(entityId); + ClientModel app = realm.addClient(entityId); app.setFullScopeAllowed(true); app.setProtocol(SamlProtocol.LOGIN_PROTOCOL); app.setAttribute(SamlProtocol.SAML_SERVER_SIGNATURE, SamlProtocol.ATTRIBUTE_TRUE_VALUE); // default to true diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java index 3c3ada6fcf..b38d5b933e 100755 --- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java +++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java @@ -4,8 +4,10 @@ import org.jboss.logging.Logger; import org.jboss.resteasy.client.ClientRequest; import org.jboss.resteasy.client.ClientResponse; import org.jboss.resteasy.client.core.executors.ApacheHttpClient4Executor; +import org.keycloak.dom.saml.v2.assertion.AssertionType; +import org.keycloak.dom.saml.v2.assertion.AttributeStatementType; +import org.keycloak.dom.saml.v2.protocol.ResponseType; import org.keycloak.events.EventBuilder; -import org.keycloak.models.ApplicationModel; import org.keycloak.models.ClientModel; import org.keycloak.models.ClientSessionModel; import org.keycloak.models.KeycloakSession; @@ -18,20 +20,17 @@ import org.keycloak.protocol.ProtocolMapper; import org.keycloak.protocol.saml.mappers.SAMLAttributeStatementMapper; import org.keycloak.protocol.saml.mappers.SAMLLoginResponseMapper; import org.keycloak.protocol.saml.mappers.SAMLRoleListMapper; +import org.keycloak.saml.common.constants.GeneralConstants; +import org.keycloak.saml.common.constants.JBossSAMLURIConstants; +import org.keycloak.saml.common.exceptions.ConfigurationException; +import org.keycloak.saml.common.exceptions.ParsingException; +import org.keycloak.saml.common.exceptions.ProcessingException; import org.keycloak.services.managers.ClientSessionCode; import org.keycloak.services.managers.ResourceAdminManager; import org.keycloak.services.messages.Messages; import org.keycloak.services.resources.RealmsResource; import org.keycloak.services.resources.admin.ClientAttributeCertificateResource; import org.keycloak.services.resources.flows.Flows; -import org.keycloak.saml.common.constants.GeneralConstants; -import org.keycloak.saml.common.constants.JBossSAMLURIConstants; -import org.keycloak.saml.common.exceptions.ConfigurationException; -import org.keycloak.saml.common.exceptions.ParsingException; -import org.keycloak.saml.common.exceptions.ProcessingException; -import org.keycloak.dom.saml.v2.assertion.AssertionType; -import org.keycloak.dom.saml.v2.assertion.AttributeStatementType; -import org.keycloak.dom.saml.v2.protocol.ResponseType; import org.w3c.dom.Document; import javax.ws.rs.core.HttpHeaders; @@ -429,7 +428,7 @@ public class SamlProtocol implements LoginProtocol { } else { logoutServiceUrl = client.getAttribute(SAML_SINGLE_LOGOUT_SERVICE_URL_REDIRECT_ATTRIBUTE); } - if (logoutServiceUrl == null && client instanceof ApplicationModel) logoutServiceUrl = ((ApplicationModel)client).getManagementUrl(); + if (logoutServiceUrl == null && client instanceof ClientModel) logoutServiceUrl = ((ClientModel)client).getManagementUrl(); if (logoutServiceUrl == null || logoutServiceUrl.trim().equals("")) return null; return ResourceAdminManager.resolveUri(uriInfo.getRequestUri(), logoutServiceUrl); @@ -438,7 +437,7 @@ public class SamlProtocol implements LoginProtocol { @Override public Response frontchannelLogout(UserSessionModel userSession, ClientSessionModel clientSession) { ClientModel client = clientSession.getClient(); - if (!(client instanceof ApplicationModel)) return null; + if (!(client instanceof ClientModel)) return null; try { if (isLogoutPostBindingForClient(clientSession)) { String bindingUri = getLogoutServiceUrl(uriInfo, client, SAML_POST_BINDING); @@ -500,8 +499,6 @@ public class SamlProtocol implements LoginProtocol { @Override public void backchannelLogout(UserSessionModel userSession, ClientSessionModel clientSession) { ClientModel client = clientSession.getClient(); - if (!(client instanceof ApplicationModel)) return; - ApplicationModel app = (ApplicationModel)client; String logoutUrl = getLogoutServiceUrl(uriInfo, client, SAML_POST_BINDING); if (logoutUrl == null) { logger.warnv("Can't do backchannel logout. No SingleLogoutService POST Binding registered for client: {1}", client.getClientId()); diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocolUtils.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocolUtils.java index 6a4c313dc7..11007c8715 100755 --- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocolUtils.java +++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocolUtils.java @@ -2,11 +2,11 @@ package org.keycloak.protocol.saml; import org.keycloak.VerificationException; import org.keycloak.models.ClientModel; -import org.keycloak.util.PemUtils; import org.keycloak.saml.common.constants.GeneralConstants; import org.keycloak.saml.common.exceptions.ProcessingException; import org.keycloak.saml.processing.api.saml.v2.sig.SAML2Signature; import org.keycloak.saml.processing.web.util.RedirectBindingUtil; +import org.keycloak.util.PemUtils; import org.w3c.dom.Document; import javax.ws.rs.core.MultivaluedMap; diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlService.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlService.java index b6dfebb36e..3b1ff99296 100755 --- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlService.java +++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlService.java @@ -11,7 +11,6 @@ import org.keycloak.events.Errors; import org.keycloak.events.EventBuilder; import org.keycloak.events.EventType; import org.keycloak.login.LoginFormsProvider; -import org.keycloak.models.ApplicationModel; import org.keycloak.models.ClientModel; import org.keycloak.models.ClientSessionModel; import org.keycloak.models.KeycloakSession; @@ -165,7 +164,7 @@ public class SamlService { RequestAbstractType requestAbstractType = (RequestAbstractType)samlObject; String issuer = requestAbstractType.getIssuer().getValue(); - ClientModel client = realm.findClient(issuer); + ClientModel client = realm.getClientByClientId(issuer); if (client == null) { event.event(EventType.LOGIN); @@ -178,7 +177,7 @@ public class SamlService { event.error(Errors.CLIENT_DISABLED); return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.LOGIN_REQUESTER_NOT_ENABLED); } - if ((client instanceof ApplicationModel) && ((ApplicationModel)client).isBearerOnly()) { + if ((client instanceof ClientModel) && ((ClientModel)client).isBearerOnly()) { event.event(EventType.LOGIN); event.error(Errors.NOT_ALLOWED); return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.BEARER_ONLY); @@ -241,8 +240,8 @@ public class SamlService { } else { redirect = client.getAttribute(SamlProtocol.SAML_ASSERTION_CONSUMER_URL_REDIRECT_ATTRIBUTE); } - if (redirect == null && client instanceof ApplicationModel) { - redirect = ((ApplicationModel)client).getManagementUrl(); + if (redirect == null && client instanceof ClientModel) { + redirect = ((ClientModel)client).getManagementUrl(); } } @@ -368,8 +367,8 @@ public class SamlService { String redirectUri = null; - if (client instanceof ApplicationModel) { - redirectUri = ((ApplicationModel)client).getBaseUrl(); + if (client instanceof ClientModel) { + redirectUri = ((ClientModel)client).getBaseUrl(); } if (redirectUri != null) { @@ -404,7 +403,6 @@ public class SamlService { protected class PostBindingProtocol extends BindingProtocol { - @Override protected void verifySignature(SAMLDocumentHolder documentHolder, ClientModel client) throws VerificationException { SamlProtocolUtils.verifyDocumentSignature(client, documentHolder.getSamlDocument()); diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/RoleNameMapper.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/RoleNameMapper.java index 1cbf93688c..e47ca3d12b 100755 --- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/RoleNameMapper.java +++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/RoleNameMapper.java @@ -1,6 +1,6 @@ package org.keycloak.protocol.saml.mappers; -import org.keycloak.models.ApplicationModel; +import org.keycloak.models.ClientModel; import org.keycloak.models.ProtocolMapperModel; import org.keycloak.models.RoleContainerModel; import org.keycloak.models.RoleModel; @@ -73,9 +73,9 @@ public class RoleNameMapper extends AbstractOIDCProtocolMapper implements SAMLRo @Override public String mapName(ProtocolMapperModel model, RoleModel roleModel) { RoleContainerModel container = roleModel.getContainer(); - ApplicationModel app = null; - if (container instanceof ApplicationModel) { - app = ((ApplicationModel) container); + ClientModel app = null; + if (container instanceof ClientModel) { + app = ((ClientModel) container); } String role = model.getConfig().get(ROLE_CONFIG); String newName = model.getConfig().get(NEW_ROLE_NAME); @@ -84,7 +84,7 @@ public class RoleNameMapper extends AbstractOIDCProtocolMapper implements SAMLRo if (scopeIndex > -1) { if (app == null) return null; appName = role.substring(0, scopeIndex); - if (!app.getName().equals(appName)) return null; + if (!app.getClientId().equals(appName)) return null; role = role.substring(scopeIndex + 1); } else { if (app != null) return null; diff --git a/saml/saml-protocol/src/main/resources/META-INF/services/org.keycloak.exportimport.ApplicationImporterFactory b/saml/saml-protocol/src/main/resources/META-INF/services/org.keycloak.exportimport.ClientImporterFactory similarity index 100% rename from saml/saml-protocol/src/main/resources/META-INF/services/org.keycloak.exportimport.ApplicationImporterFactory rename to saml/saml-protocol/src/main/resources/META-INF/services/org.keycloak.exportimport.ClientImporterFactory diff --git a/services/pom.xml b/services/pom.xml index e5fde97b37..ea6e90e600 100755 --- a/services/pom.xml +++ b/services/pom.xml @@ -102,12 +102,6 @@ ${project.version} provided - - org.keycloak - keycloak-picketlink-api - ${project.version} - provided - org.jboss.spec.javax.servlet jboss-servlet-api_3.0_spec diff --git a/services/src/main/java/org/keycloak/exportimport/ApplicationImportSpi.java b/services/src/main/java/org/keycloak/exportimport/ClientImportSpi.java similarity index 71% rename from services/src/main/java/org/keycloak/exportimport/ApplicationImportSpi.java rename to services/src/main/java/org/keycloak/exportimport/ClientImportSpi.java index 4493b19e22..6fe071e536 100755 --- a/services/src/main/java/org/keycloak/exportimport/ApplicationImportSpi.java +++ b/services/src/main/java/org/keycloak/exportimport/ClientImportSpi.java @@ -7,20 +7,20 @@ import org.keycloak.provider.Spi; /** * @author Marek Posolda */ -public class ApplicationImportSpi implements Spi { +public class ClientImportSpi implements Spi { @Override public String getName() { - return "application-import"; + return "client-import"; } @Override public Class getProviderClass() { - return ApplicationImporter.class; + return ClientImporter.class; } @Override public Class getProviderFactoryClass() { - return ApplicationImporterFactory.class; + return ClientImporterFactory.class; } } diff --git a/services/src/main/java/org/keycloak/exportimport/ApplicationImporter.java b/services/src/main/java/org/keycloak/exportimport/ClientImporter.java similarity index 67% rename from services/src/main/java/org/keycloak/exportimport/ApplicationImporter.java rename to services/src/main/java/org/keycloak/exportimport/ClientImporter.java index f4c526ef40..3d236fb16e 100755 --- a/services/src/main/java/org/keycloak/exportimport/ApplicationImporter.java +++ b/services/src/main/java/org/keycloak/exportimport/ClientImporter.java @@ -5,11 +5,11 @@ import org.keycloak.provider.Provider; import org.keycloak.services.resources.admin.RealmAuth; /** - * Provider plugin interface for importing applications from an arbitrary configuration format + * Provider plugin interface for importing clients from an arbitrary configuration format * * @author Bill Burke * @version $Revision: 1 $ */ -public interface ApplicationImporter extends Provider { +public interface ClientImporter extends Provider { public Object createJaxrsService(RealmModel realm, RealmAuth auth); } diff --git a/services/src/main/java/org/keycloak/exportimport/ApplicationImporterFactory.java b/services/src/main/java/org/keycloak/exportimport/ClientImporterFactory.java similarity index 52% rename from services/src/main/java/org/keycloak/exportimport/ApplicationImporterFactory.java rename to services/src/main/java/org/keycloak/exportimport/ClientImporterFactory.java index b73e2e68c3..e70bbfaea4 100755 --- a/services/src/main/java/org/keycloak/exportimport/ApplicationImporterFactory.java +++ b/services/src/main/java/org/keycloak/exportimport/ClientImporterFactory.java @@ -3,11 +3,11 @@ package org.keycloak.exportimport; import org.keycloak.provider.ProviderFactory; /** - * Provider plugin interface for importing applications from an arbitrary configuration format + * Provider plugin interface for importing clients from an arbitrary configuration format * * @author Bill Burke * @version $Revision: 1 $ */ -public interface ApplicationImporterFactory extends ProviderFactory { +public interface ClientImporterFactory extends ProviderFactory { public String getDisplayName(); } diff --git a/services/src/main/java/org/keycloak/protocol/AbstractLoginProtocolFactory.java b/services/src/main/java/org/keycloak/protocol/AbstractLoginProtocolFactory.java index f009c6b94a..aa86a26ec7 100755 --- a/services/src/main/java/org/keycloak/protocol/AbstractLoginProtocolFactory.java +++ b/services/src/main/java/org/keycloak/protocol/AbstractLoginProtocolFactory.java @@ -1,24 +1,18 @@ package org.keycloak.protocol; -import org.jboss.logging.Logger; import org.keycloak.Config; import org.keycloak.models.ClientModel; -import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSessionFactory; import org.keycloak.models.RealmModel; import org.keycloak.provider.ProviderEvent; import org.keycloak.provider.ProviderEventListener; -import java.util.List; - /** * @author Bill Burke * @version $Revision: 1 $ */ public abstract class AbstractLoginProtocolFactory implements LoginProtocolFactory { - private static final Logger logger = Logger.getLogger(AbstractLoginProtocolFactory.class); - @Override public void init(Config.Scope config) { } @@ -34,8 +28,6 @@ public abstract class AbstractLoginProtocolFactory implements LoginProtocolFacto } } }); - - } protected abstract void addDefaults(ClientModel realm); diff --git a/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocol.java b/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocol.java index 581503718b..88525dbd71 100755 --- a/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocol.java +++ b/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocol.java @@ -27,7 +27,7 @@ import org.keycloak.OAuth2Constants; import org.keycloak.events.Details; import org.keycloak.events.EventBuilder; import org.keycloak.events.EventType; -import org.keycloak.models.ApplicationModel; +import org.keycloak.models.ClientModel; import org.keycloak.models.ClientSessionModel; import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; @@ -164,8 +164,8 @@ public class OIDCLoginProtocol implements LoginProtocol { @Override public void backchannelLogout(UserSessionModel userSession, ClientSessionModel clientSession) { - if (!(clientSession.getClient() instanceof ApplicationModel)) return; - ApplicationModel app = (ApplicationModel)clientSession.getClient(); + if (!(clientSession.getClient() instanceof ClientModel)) return; + ClientModel app = (ClientModel)clientSession.getClient(); ApacheHttpClient4Executor executor = ResourceAdminManager.createExecutor(); try { diff --git a/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java b/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java index e21d0911f1..8d9ab8c7ea 100755 --- a/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java +++ b/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java @@ -8,7 +8,6 @@ import org.keycloak.events.EventBuilder; import org.keycloak.jose.jws.JWSBuilder; import org.keycloak.jose.jws.JWSInput; import org.keycloak.jose.jws.crypto.RSAProvider; -import org.keycloak.models.ApplicationModel; import org.keycloak.models.ClientModel; import org.keycloak.models.ClientSessionModel; import org.keycloak.models.KeycloakSession; @@ -233,8 +232,8 @@ public class TokenManager { if (client.isFullScopeAllowed()) return roleMappings; Set scopeMappings = client.getScopeMappings(); - if (client instanceof ApplicationModel) { - scopeMappings.addAll(((ApplicationModel) client).getRoles()); + if (client instanceof ClientModel) { + scopeMappings.addAll(((ClientModel) client).getRoles()); } for (RoleModel role : roleMappings) { @@ -261,12 +260,12 @@ public class TokenManager { for (Map.Entry entry : token.getResourceAccess().entrySet()) { AccessToken.Access appAccess = newToken.getResourceAccess(entry.getKey()); if (appAccess == null && !entry.getValue().getRoles().isEmpty()) { - throw new OAuthErrorException(OAuthErrorException.INVALID_SCOPE, "User or application no longer has role permissions for application key: " + entry.getKey()); + throw new OAuthErrorException(OAuthErrorException.INVALID_SCOPE, "User or client no longer has role permissions for client key: " + entry.getKey()); } for (String roleName : entry.getValue().getRoles()) { if (!appAccess.getRoles().contains(roleName)) { - throw new OAuthErrorException(OAuthErrorException.INVALID_SCOPE, "User no long has permission for application role " + roleName); + throw new OAuthErrorException(OAuthErrorException.INVALID_SCOPE, "User no long has permission for client role " + roleName); } } } @@ -339,10 +338,10 @@ public class TokenManager { return; } else { - ApplicationModel app = (ApplicationModel) role.getContainer(); - access = token.getResourceAccess(app.getName()); + ClientModel app = (ClientModel) role.getContainer(); + access = token.getResourceAccess(app.getClientId()); if (access == null) { - access = token.addAccess(app.getName()); + access = token.addAccess(app.getClientId()); if (app.isSurrogateAuthRequired()) access.verifyCaller(true); } else if (access.isUserInRole(role.getName())) return; diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpoint.java index dfe6b2f0c5..e33cb67f1e 100755 --- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpoint.java +++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpoint.java @@ -11,7 +11,6 @@ import org.keycloak.events.Errors; import org.keycloak.events.EventBuilder; import org.keycloak.events.EventType; import org.keycloak.login.LoginFormsProvider; -import org.keycloak.models.ApplicationModel; import org.keycloak.models.ClientModel; import org.keycloak.models.ClientSessionModel; import org.keycloak.models.IdentityProviderModel; @@ -168,13 +167,13 @@ public class AuthorizationEndpoint { event.client(clientId); - client = realm.findClient(clientId); + client = realm.getClientByClientId(clientId); if (client == null) { event.error(Errors.CLIENT_NOT_FOUND); throw new ErrorPageException(session, realm, uriInfo, headers, Messages.CLIENT_NOT_FOUND ); } - if ((client instanceof ApplicationModel) && ((ApplicationModel) client).isBearerOnly()) { + if ((client instanceof ClientModel) && ((ClientModel) client).isBearerOnly()) { event.error(Errors.NOT_ALLOWED); throw new ErrorPageException(session, realm, uriInfo, headers, Messages.BEARER_ONLY ); } diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/LoginStatusIframeEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/LoginStatusIframeEndpoint.java index 30359d12f3..156ee4465c 100644 --- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/LoginStatusIframeEndpoint.java +++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/LoginStatusIframeEndpoint.java @@ -42,7 +42,7 @@ public class LoginStatusIframeEndpoint { throw new BadRequestException("Invalid origin"); } - ClientModel client = realm.findClient(client_id); + ClientModel client = realm.getClientByClientId(client_id); if (client == null) { throw new NotFoundException("could not find client"); } diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/LogoutEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/LogoutEndpoint.java index a61c8112e7..5bab0e0d11 100755 --- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/LogoutEndpoint.java +++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/LogoutEndpoint.java @@ -10,7 +10,6 @@ import org.keycloak.events.Details; import org.keycloak.events.Errors; import org.keycloak.events.EventBuilder; import org.keycloak.events.EventType; -import org.keycloak.models.ApplicationModel; import org.keycloak.models.ClientModel; import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; @@ -146,9 +145,9 @@ public class LogoutEndpoint { * authenticate the client if it is not public. * * If the client is a confidential client - * you must include the client-id (application name or oauth client name) and secret in an Basic Auth Authorization header. + * you must include the client-id and secret in an Basic Auth Authorization header. * - * If the client is a public client, then you must include a "client_id" form parameter with the app's or oauth client's name. + * If the client is a public client, then you must include a "client_id" form parameter. * * returns 204 if successful, 400 if not with a json error response. * @@ -191,7 +190,7 @@ public class LogoutEndpoint { private ClientModel authorizeClient(String authorizationHeader, MultivaluedMap formData, EventBuilder event) { ClientModel client = AuthorizeClientUtil.authorizeClient(authorizationHeader, formData, event, realm); - if ( (client instanceof ApplicationModel) && ((ApplicationModel)client).isBearerOnly()) { + if ( (client instanceof ClientModel) && ((ClientModel)client).isBearerOnly()) { throw new ErrorResponseException("invalid_client", "Bearer-only not allowed", Response.Status.BAD_REQUEST); } diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenEndpoint.java index bd211e4e95..60b1b98db6 100755 --- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenEndpoint.java +++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenEndpoint.java @@ -10,7 +10,6 @@ import org.keycloak.events.Details; import org.keycloak.events.Errors; import org.keycloak.events.EventBuilder; import org.keycloak.events.EventType; -import org.keycloak.models.ApplicationModel; import org.keycloak.models.ClientModel; import org.keycloak.models.ClientSessionModel; import org.keycloak.models.KeycloakSession; @@ -20,7 +19,6 @@ import org.keycloak.models.UserSessionModel; import org.keycloak.models.UserSessionProvider; import org.keycloak.models.utils.KeycloakModelUtils; import org.keycloak.protocol.oidc.OIDCLoginProtocol; -import org.keycloak.protocol.oidc.OIDCLoginProtocolService; import org.keycloak.protocol.oidc.TokenManager; import org.keycloak.protocol.oidc.utils.AuthorizeClientUtil; import org.keycloak.representations.AccessToken; @@ -31,7 +29,6 @@ import org.keycloak.services.managers.ClientSessionCode; import org.keycloak.services.resources.Cors; import org.keycloak.services.resources.flows.Urls; -import javax.ws.rs.Consumes; import javax.ws.rs.OPTIONS; import javax.ws.rs.POST; import javax.ws.rs.core.Context; @@ -147,7 +144,7 @@ public class TokenEndpoint { String authorizationHeader = headers.getRequestHeaders().getFirst(HttpHeaders.AUTHORIZATION); client = AuthorizeClientUtil.authorizeClient(authorizationHeader, formParams, event, realm); - if ((client instanceof ApplicationModel) && ((ApplicationModel) client).isBearerOnly()) { + if ((client instanceof ClientModel) && ((ClientModel) client).isBearerOnly()) { throw new ErrorResponseException("invalid_client", "Bearer-only not allowed", Response.Status.BAD_REQUEST); } } @@ -234,15 +231,15 @@ public class TokenEndpoint { throw new ErrorResponseException("invalid_grant", "Session not active", Response.Status.BAD_REQUEST); } - String adapterSessionId = formParams.getFirst(AdapterConstants.APPLICATION_SESSION_STATE); + String adapterSessionId = formParams.getFirst(AdapterConstants.CLIENT_SESSION_STATE); if (adapterSessionId != null) { - String adapterSessionHost = formParams.getFirst(AdapterConstants.APPLICATION_SESSION_HOST); + String adapterSessionHost = formParams.getFirst(AdapterConstants.CLIENT_SESSION_HOST); logger.debugf("Adapter Session '%s' saved in ClientSession for client '%s'. Host is '%s'", adapterSessionId, client.getClientId(), adapterSessionHost); - event.detail(AdapterConstants.APPLICATION_SESSION_STATE, adapterSessionId); - clientSession.setNote(AdapterConstants.APPLICATION_SESSION_STATE, adapterSessionId); - event.detail(AdapterConstants.APPLICATION_SESSION_HOST, adapterSessionHost); - clientSession.setNote(AdapterConstants.APPLICATION_SESSION_HOST, adapterSessionHost); + event.detail(AdapterConstants.CLIENT_SESSION_STATE, adapterSessionId); + clientSession.setNote(AdapterConstants.CLIENT_SESSION_STATE, adapterSessionId); + event.detail(AdapterConstants.CLIENT_SESSION_HOST, adapterSessionHost); + clientSession.setNote(AdapterConstants.CLIENT_SESSION_HOST, adapterSessionHost); } AccessToken token = tokenManager.createClientAccessToken(session, accessCode.getRequestedRoles(), realm, client, user, userSession, clientSession); diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/UserInfoEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/UserInfoEndpoint.java index e4f5c41d48..ba2f99ceae 100755 --- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/UserInfoEndpoint.java +++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/UserInfoEndpoint.java @@ -122,7 +122,7 @@ public class UserInfoEndpoint { } UserSessionModel userSession = session.sessions().getUserSession(realm, token.getSessionState()); - ClientModel clientModel = realm.findClient(token.getIssuedFor()); + ClientModel clientModel = realm.getClientByClientId(token.getIssuedFor()); UserModel userModel = userSession.getUser(); AccessToken userInfo = new AccessToken(); tokenManager.transformAccessToken(session, userInfo, realm, clientModel, userModel, userSession, null); diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/ValidateTokenEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/ValidateTokenEndpoint.java index 31499d1bd1..249aa30ddb 100644 --- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/ValidateTokenEndpoint.java +++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/ValidateTokenEndpoint.java @@ -88,7 +88,7 @@ public class ValidateTokenEndpoint { error.put(OAuth2Constants.ERROR, e.getError()); if (e.getDescription() != null) error.put(OAuth2Constants.ERROR_DESCRIPTION, e.getDescription()); event.error(Errors.INVALID_TOKEN); - return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build(); + return Response.status(Response.Status.BAD_REQUEST).entity(error).type(MediaType.APPLICATION_JSON_TYPE).build(); } event.success(); diff --git a/services/src/main/java/org/keycloak/protocol/oidc/utils/AuthorizeClientUtil.java b/services/src/main/java/org/keycloak/protocol/oidc/utils/AuthorizeClientUtil.java index 1a78b641f9..a8a9e2a495 100644 --- a/services/src/main/java/org/keycloak/protocol/oidc/utils/AuthorizeClientUtil.java +++ b/services/src/main/java/org/keycloak/protocol/oidc/utils/AuthorizeClientUtil.java @@ -10,6 +10,7 @@ import org.keycloak.models.RealmModel; import org.keycloak.util.BasicAuthHelper; import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.core.Response; import java.util.HashMap; @@ -39,18 +40,18 @@ public class AuthorizeClientUtil { Map error = new HashMap(); error.put(OAuth2Constants.ERROR, "invalid_client"); error.put(OAuth2Constants.ERROR_DESCRIPTION, "Could not find client"); - throw new BadRequestException("Could not find client", Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build()); + throw new BadRequestException("Could not find client", Response.status(Response.Status.BAD_REQUEST).entity(error).type(MediaType.APPLICATION_JSON_TYPE).build()); } event.client(client_id); - ClientModel client = realm.findClient(client_id); + ClientModel client = realm.getClientByClientId(client_id); if (client == null) { Map error = new HashMap(); error.put(OAuth2Constants.ERROR, "invalid_client"); error.put(OAuth2Constants.ERROR_DESCRIPTION, "Could not find client"); event.error(Errors.CLIENT_NOT_FOUND); - throw new BadRequestException("Could not find client", Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build()); + throw new BadRequestException("Could not find client", Response.status(Response.Status.BAD_REQUEST).entity(error).type(MediaType.APPLICATION_JSON_TYPE).build()); } if (!client.isEnabled()) { @@ -58,7 +59,7 @@ public class AuthorizeClientUtil { error.put(OAuth2Constants.ERROR, "invalid_client"); error.put(OAuth2Constants.ERROR_DESCRIPTION, "Client is not enabled"); event.error(Errors.CLIENT_DISABLED); - throw new BadRequestException("Client is not enabled", Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build()); + throw new BadRequestException("Client is not enabled", Response.status(Response.Status.BAD_REQUEST).entity(error).type(MediaType.APPLICATION_JSON_TYPE).build()); } if (!client.isPublicClient()) { @@ -66,7 +67,7 @@ public class AuthorizeClientUtil { Map error = new HashMap(); error.put(OAuth2Constants.ERROR, "unauthorized_client"); event.error(Errors.INVALID_CLIENT_CREDENTIALS); - throw new BadRequestException("Unauthorized Client", Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build()); + throw new BadRequestException("Unauthorized Client", Response.status(Response.Status.BAD_REQUEST).entity(error).type(MediaType.APPLICATION_JSON_TYPE).build()); } } diff --git a/services/src/main/java/org/keycloak/protocol/oidc/utils/RedirectUtils.java b/services/src/main/java/org/keycloak/protocol/oidc/utils/RedirectUtils.java index 2fa3aeedb7..68da8259a3 100644 --- a/services/src/main/java/org/keycloak/protocol/oidc/utils/RedirectUtils.java +++ b/services/src/main/java/org/keycloak/protocol/oidc/utils/RedirectUtils.java @@ -1,10 +1,8 @@ package org.keycloak.protocol.oidc.utils; import org.jboss.logging.Logger; -import org.keycloak.models.ApplicationModel; import org.keycloak.models.ClientModel; import org.keycloak.models.Constants; -import org.keycloak.models.OAuthClientModel; import org.keycloak.models.RealmModel; import org.keycloak.services.resources.flows.Urls; @@ -46,12 +44,7 @@ public class RedirectUtils { private static Set getValidateRedirectUris(RealmModel realm) { Set redirects = new HashSet(); - for (ApplicationModel client : realm.getApplications()) { - for (String redirect : client.getRedirectUris()) { - redirects.add(redirect); - } - } - for (OAuthClientModel client : realm.getOAuthClients()) { + for (ClientModel client : realm.getClients()) { for (String redirect : client.getRedirectUris()) { redirects.add(redirect); } diff --git a/services/src/main/java/org/keycloak/services/ErrorResponseException.java b/services/src/main/java/org/keycloak/services/ErrorResponseException.java index bf9f278429..0dd3e13b8d 100644 --- a/services/src/main/java/org/keycloak/services/ErrorResponseException.java +++ b/services/src/main/java/org/keycloak/services/ErrorResponseException.java @@ -6,6 +6,7 @@ import org.keycloak.models.RealmModel; import org.keycloak.services.resources.flows.Flows; import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; import java.util.HashMap; @@ -33,7 +34,7 @@ public class ErrorResponseException extends WebApplicationException { if (errorDescription != null) { e.put(OAuth2Constants.ERROR_DESCRIPTION, errorDescription); } - return Response.status(status).entity(e).type("application/json").build(); + return Response.status(status).entity(e).type(MediaType.APPLICATION_JSON_TYPE).build(); } } diff --git a/services/src/main/java/org/keycloak/services/managers/ApplianceBootstrap.java b/services/src/main/java/org/keycloak/services/managers/ApplianceBootstrap.java index 96d97e34f0..8760ff01b3 100755 --- a/services/src/main/java/org/keycloak/services/managers/ApplianceBootstrap.java +++ b/services/src/main/java/org/keycloak/services/managers/ApplianceBootstrap.java @@ -4,7 +4,7 @@ import org.jboss.logging.Logger; import org.keycloak.Config; import org.keycloak.enums.SslRequired; import org.keycloak.models.AdminRoles; -import org.keycloak.models.ApplicationModel; +import org.keycloak.models.ClientModel; import org.keycloak.models.Constants; import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSessionFactory; @@ -71,7 +71,7 @@ public class ApplianceBootstrap { RoleModel adminRole = realm.getRole(AdminRoles.ADMIN); adminUser.grantRole(adminRole); - ApplicationModel accountApp = realm.getApplicationNameMap().get(Constants.ACCOUNT_MANAGEMENT_APP); + ClientModel accountApp = realm.getClientNameMap().get(Constants.ACCOUNT_MANAGEMENT_CLIENT_ID); for (String r : accountApp.getDefaultRoles()) { adminUser.grantRole(accountApp.getRole(r)); } diff --git a/services/src/main/java/org/keycloak/services/managers/Auth.java b/services/src/main/java/org/keycloak/services/managers/Auth.java index 1527ea5153..8d76e56cb6 100755 --- a/services/src/main/java/org/keycloak/services/managers/Auth.java +++ b/services/src/main/java/org/keycloak/services/managers/Auth.java @@ -1,6 +1,5 @@ package org.keycloak.services.managers; -import org.keycloak.models.ApplicationModel; import org.keycloak.models.ClientModel; import org.keycloak.models.ClientSessionModel; import org.keycloak.models.RealmModel; @@ -81,18 +80,18 @@ public class Auth { return false; } - public boolean hasAppRole(ApplicationModel app, String role) { + public boolean hasClientRole(ClientModel app, String role) { if (cookie) { return user.hasRole(app.getRole(role)); } else { - AccessToken.Access access = token.getResourceAccess(app.getName()); + AccessToken.Access access = token.getResourceAccess(app.getClientId()); return access != null && access.isUserInRole(role); } } - public boolean hasOneOfAppRole(ApplicationModel app, String... roles) { + public boolean hasOneOfAppRole(ClientModel app, String... roles) { for (String r : roles) { - if (hasAppRole(app, r)) { + if (hasClientRole(app, r)) { return true; } } diff --git a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java index 8ebcf74eb7..8cd948309b 100755 --- a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java +++ b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java @@ -12,7 +12,6 @@ import org.keycloak.events.EventBuilder; import org.keycloak.events.EventType; import org.keycloak.jose.jws.JWSBuilder; import org.keycloak.login.LoginFormsProvider; -import org.keycloak.models.ApplicationModel; import org.keycloak.models.ClientModel; import org.keycloak.models.ClientSessionModel; import org.keycloak.models.KeycloakSession; @@ -111,7 +110,7 @@ public class AuthenticationManager { for (ClientSessionModel clientSession : userSession.getClientSessions()) { ClientModel client = clientSession.getClient(); - if (client instanceof ApplicationModel && !client.isFrontchannelLogout() && clientSession.getAction() != ClientSessionModel.Action.LOGGED_OUT) { + if (client instanceof ClientModel && !client.isFrontchannelLogout() && clientSession.getAction() != ClientSessionModel.Action.LOGGED_OUT) { String authMethod = clientSession.getAuthMethod(); if (authMethod == null) continue; // must be a keycloak service like account LoginProtocol protocol = session.getProvider(LoginProtocol.class, authMethod); @@ -145,7 +144,7 @@ public class AuthenticationManager { redirectClients.add(clientSession); continue; } - if (client instanceof ApplicationModel && !client.isFrontchannelLogout()) { + if (client instanceof ClientModel && !client.isFrontchannelLogout()) { String authMethod = clientSession.getAuthMethod(); if (authMethod == null) continue; // must be a keycloak service like account LoginProtocol protocol = session.getProvider(LoginProtocol.class, authMethod); @@ -381,13 +380,9 @@ public class AuthenticationManager { isEmailVerificationRequired(realm, user); ClientModel client = clientSession.getClient(); - boolean isResource = client instanceof ApplicationModel; ClientSessionCode accessCode = new ClientSessionCode(realm, clientSession); - - logger.debugv("processAccessCode: isResource: {0}", isResource); - logger.debugv("processAccessCode: go to oauth page?: {0}", - !isResource); + logger.debugv("processAccessCode: go to oauth page?: {0}", client.isConsentRequired()); event.detail(Details.CODE_ID, clientSession.getId()); @@ -417,7 +412,7 @@ public class AuthenticationManager { } } - if (!isResource) { + if (client.isConsentRequired()) { accessCode.setAction(ClientSessionModel.Action.OAUTH_GRANT); List realmRoles = new LinkedList(); @@ -426,7 +421,7 @@ public class AuthenticationManager { if (r.getContainer() instanceof RealmModel) { realmRoles.add(r); } else { - resourceRoles.add(((ApplicationModel) r.getContainer()).getName(), r); + resourceRoles.add(((ClientModel) r.getContainer()).getClientId(), r); } } diff --git a/services/src/main/java/org/keycloak/services/managers/ApplicationManager.java b/services/src/main/java/org/keycloak/services/managers/ClientManager.java similarity index 70% rename from services/src/main/java/org/keycloak/services/managers/ApplicationManager.java rename to services/src/main/java/org/keycloak/services/managers/ClientManager.java index 5463f39d16..18d4d09051 100755 --- a/services/src/main/java/org/keycloak/services/managers/ApplicationManager.java +++ b/services/src/main/java/org/keycloak/services/managers/ClientManager.java @@ -3,7 +3,7 @@ package org.keycloak.services.managers; import org.codehaus.jackson.annotate.JsonProperty; import org.codehaus.jackson.annotate.JsonPropertyOrder; import org.jboss.logging.Logger; -import org.keycloak.models.ApplicationModel; +import org.keycloak.models.ClientModel; import org.keycloak.models.RealmModel; import org.keycloak.models.UserSessionProvider; import org.keycloak.models.utils.KeycloakModelUtils; @@ -24,27 +24,27 @@ import java.util.TreeSet; * @author Bill Burke * @version $Revision: 1 $ */ -public class ApplicationManager { - protected Logger logger = Logger.getLogger(ApplicationManager.class); +public class ClientManager { + protected Logger logger = Logger.getLogger(ClientManager.class); protected RealmManager realmManager; - public ApplicationManager(RealmManager realmManager) { + public ClientManager(RealmManager realmManager) { this.realmManager = realmManager; } - public ApplicationManager() { + public ClientManager() { } - public ApplicationModel createApplication(RealmModel realm, String name) { - return KeycloakModelUtils.createApplication(realm, name); + public ClientModel createClient(RealmModel realm, String name) { + return KeycloakModelUtils.createClient(realm, name); } - public boolean removeApplication(RealmModel realm, ApplicationModel application) { - if (realm.removeApplication(application.getId())) { + public boolean removeClient(RealmModel realm, ClientModel client) { + if (realm.removeClient(client.getId())) { UserSessionProvider sessions = realmManager.getSession().sessions(); if (sessions != null) { - sessions.onClientRemoved(realm, application); + sessions.onClientRemoved(realm, client); } return true; } else { @@ -52,8 +52,8 @@ public class ApplicationManager { } } - public Set validateRegisteredNodes(ApplicationModel application) { - Map registeredNodes = application.getRegisteredNodes(); + public Set validateRegisteredNodes(ClientModel client) { + Map registeredNodes = client.getRegisteredNodes(); if (registeredNodes == null || registeredNodes.isEmpty()) { return Collections.emptySet(); } @@ -61,11 +61,11 @@ public class ApplicationManager { int currentTime = Time.currentTime(); Set validatedNodes = new TreeSet(); - if (application.getNodeReRegistrationTimeout() > 0) { + if (client.getNodeReRegistrationTimeout() > 0) { List toRemove = new LinkedList(); for (Map.Entry entry : registeredNodes.entrySet()) { Integer lastReRegistration = entry.getValue(); - if (lastReRegistration + application.getNodeReRegistrationTimeout() < currentTime) { + if (lastReRegistration + client.getNodeReRegistrationTimeout() < currentTime) { toRemove.add(entry.getKey()); } else { validatedNodes.add(entry.getKey()); @@ -74,7 +74,7 @@ public class ApplicationManager { // Remove time-outed nodes for (String node : toRemove) { - application.unregisterNode(node); + client.unregisterNode(node); } } else { // Periodic node reRegistration is disabled, so allow all nodes @@ -141,22 +141,22 @@ public class ApplicationManager { } - public InstallationAdapterConfig toInstallationRepresentation(RealmModel realmModel, ApplicationModel applicationModel, URI baseUri) { + public InstallationAdapterConfig toInstallationRepresentation(RealmModel realmModel, ClientModel clientModel, URI baseUri) { InstallationAdapterConfig rep = new InstallationAdapterConfig(); rep.setRealm(realmModel.getName()); rep.setRealmKey(realmModel.getPublicKeyPem()); rep.setSslRequired(realmModel.getSslRequired().name().toLowerCase()); - if (applicationModel.isPublicClient() && !applicationModel.isBearerOnly()) rep.setPublicClient(true); - if (applicationModel.isBearerOnly()) rep.setBearerOnly(true); - if (!applicationModel.isBearerOnly()) rep.setAuthServerUrl(baseUri.toString()); - if (applicationModel.getRoles().size() > 0) rep.setUseResourceRoleMappings(true); + if (clientModel.isPublicClient() && !clientModel.isBearerOnly()) rep.setPublicClient(true); + if (clientModel.isBearerOnly()) rep.setBearerOnly(true); + if (!clientModel.isBearerOnly()) rep.setAuthServerUrl(baseUri.toString()); + if (clientModel.getRoles().size() > 0) rep.setUseResourceRoleMappings(true); - rep.setResource(applicationModel.getName()); + rep.setResource(clientModel.getClientId()); - if (!applicationModel.isBearerOnly() && !applicationModel.isPublicClient()) { + if (!clientModel.isBearerOnly() && !clientModel.isPublicClient()) { Map creds = new HashMap(); - String cred = applicationModel.getSecret(); + String cred = clientModel.getSecret(); creds.put(CredentialRepresentation.SECRET, cred); rep.setCredentials(creds); } @@ -164,27 +164,27 @@ public class ApplicationManager { return rep; } - public String toJBossSubsystemConfig(RealmModel realmModel, ApplicationModel applicationModel, URI baseUri) { + public String toJBossSubsystemConfig(RealmModel realmModel, ClientModel clientModel, URI baseUri) { StringBuffer buffer = new StringBuffer(); buffer.append("\n"); buffer.append(" ").append(realmModel.getName()).append("\n"); buffer.append(" ").append(realmModel.getPublicKeyPem()).append("\n"); - if (applicationModel.isBearerOnly()){ + if (clientModel.isBearerOnly()){ buffer.append(" true\n"); } else { buffer.append(" ").append(baseUri.toString()).append("\n"); - if (applicationModel.isPublicClient() && !applicationModel.isBearerOnly()) { + if (clientModel.isPublicClient() && !clientModel.isBearerOnly()) { buffer.append(" true\n"); } } buffer.append(" ").append(realmModel.getSslRequired().name()).append("\n"); - buffer.append(" ").append(applicationModel.getName()).append("\n"); - String cred = applicationModel.getSecret(); - if (!applicationModel.isBearerOnly() && !applicationModel.isPublicClient()) { + buffer.append(" ").append(clientModel.getClientId()).append("\n"); + String cred = clientModel.getSecret(); + if (!clientModel.isBearerOnly() && !clientModel.isPublicClient()) { buffer.append(" ").append(cred).append("\n"); } - if (applicationModel.getRoles().size() > 0) { + if (clientModel.getRoles().size() > 0) { buffer.append(" true\n"); } buffer.append("\n"); diff --git a/services/src/main/java/org/keycloak/services/managers/OAuthClientManager.java b/services/src/main/java/org/keycloak/services/managers/OAuthClientManager.java deleted file mode 100755 index 25ce6a239a..0000000000 --- a/services/src/main/java/org/keycloak/services/managers/OAuthClientManager.java +++ /dev/null @@ -1,96 +0,0 @@ -package org.keycloak.services.managers; - -import org.codehaus.jackson.annotate.JsonProperty; -import org.codehaus.jackson.annotate.JsonPropertyOrder; -import org.keycloak.models.OAuthClientModel; -import org.keycloak.models.RealmModel; -import org.keycloak.models.UserSessionProvider; -import org.keycloak.representations.adapters.config.BaseRealmConfig; -import org.keycloak.representations.idm.CredentialRepresentation; - -import java.net.URI; -import java.util.HashMap; -import java.util.Map; - -/** - * @author Bill Burke - * @version $Revision: 1 $ - */ -public class OAuthClientManager { - - private RealmManager realmManager; - - public OAuthClientManager() { - } - - public OAuthClientManager(RealmManager realmManager) { - this.realmManager = realmManager; - } - - public boolean removeClient(RealmModel realm, OAuthClientModel client) { - if (realm.removeOAuthClient(client.getId())) { - UserSessionProvider sessions = realmManager.getSession().sessions(); - if (sessions != null) { - realmManager.getSession().sessions().onClientRemoved(realm, client); - } - return true; - } else { - return false; - } - } - - @JsonPropertyOrder({"realm", "realm-public-key", "auth-server-url", "ssl-required", - "resource", "public-client", "credentials"}) - public static class InstallationAdapterConfig extends BaseRealmConfig { - @JsonProperty("public-client") - protected Boolean publicClient; - @JsonProperty("resource") - protected String resource; - @JsonProperty("credentials") - protected Map credentials; - - public String getResource() { - return resource; - } - - public void setResource(String resource) { - this.resource = resource; - } - - public Map getCredentials() { - return credentials; - } - - public void setCredentials(Map credentials) { - this.credentials = credentials; - } - - public Boolean getPublicClient() { - return publicClient; - } - - public void setPublicClient(Boolean publicClient) { - this.publicClient = publicClient; - } - } - - - public InstallationAdapterConfig toInstallationRepresentation(RealmModel realmModel, OAuthClientModel model, URI baseUri) { - InstallationAdapterConfig rep = new InstallationAdapterConfig(); - rep.setRealm(realmModel.getName()); - rep.setRealmKey(realmModel.getPublicKeyPem()); - rep.setSslRequired(realmModel.getSslRequired().name().toLowerCase()); - rep.setAuthServerUrl(baseUri.toString()); - if (model.isPublicClient()) rep.setPublicClient(true); - - rep.setResource(model.getClientId()); - - if (!model.isPublicClient()) { - Map creds = new HashMap(); - creds.put(CredentialRepresentation.SECRET, model.getSecret()); - rep.setCredentials(creds); - } - - return rep; - } -} diff --git a/services/src/main/java/org/keycloak/services/managers/RealmManager.java b/services/src/main/java/org/keycloak/services/managers/RealmManager.java index 138b0e4e78..53b460a04c 100755 --- a/services/src/main/java/org/keycloak/services/managers/RealmManager.java +++ b/services/src/main/java/org/keycloak/services/managers/RealmManager.java @@ -6,7 +6,7 @@ import org.keycloak.enums.SslRequired; import org.keycloak.exportimport.util.ImportUtils; import org.keycloak.models.AccountRoles; import org.keycloak.models.AdminRoles; -import org.keycloak.models.ApplicationModel; +import org.keycloak.models.ClientModel; import org.keycloak.models.BrowserSecurityHeaders; import org.keycloak.models.Constants; import org.keycloak.models.KeycloakSession; @@ -18,14 +18,13 @@ import org.keycloak.models.UserModel; import org.keycloak.models.UserSessionProvider; import org.keycloak.models.utils.KeycloakModelUtils; import org.keycloak.models.utils.RepresentationToModel; -import org.keycloak.representations.idm.ApplicationRepresentation; +import org.keycloak.representations.idm.ClientRepresentation; import org.keycloak.representations.idm.RealmEventsConfigRepresentation; import org.keycloak.representations.idm.RealmRepresentation; import org.keycloak.timer.TimerProvider; import java.util.Collections; import java.util.HashSet; -import java.util.LinkedList; import java.util.List; /** @@ -91,8 +90,8 @@ public class RealmManager { } protected void setupAdminConsole(RealmModel realm) { - ApplicationModel adminConsole = realm.getApplicationByName(Constants.ADMIN_CONSOLE_APPLICATION); - if (adminConsole == null) adminConsole = new ApplicationManager(this).createApplication(realm, Constants.ADMIN_CONSOLE_APPLICATION); + ClientModel adminConsole = realm.getClientByClientId(Constants.ADMIN_CONSOLE_CLIENT_ID); + if (adminConsole == null) adminConsole = new ClientManager(this).createClient(realm, Constants.ADMIN_CONSOLE_CLIENT_ID); String baseUrl = contextPath + "/admin/" + realm.getName() + "/console"; adminConsole.setBaseUrl(baseUrl + "/index.html"); adminConsole.setEnabled(true); @@ -104,18 +103,18 @@ public class RealmManager { if (realm.getName().equals(Config.getAdminRealm())) { adminRole = realm.getRole(AdminRoles.ADMIN); } else { - String realmAdminApplicationName = getRealmAdminApplicationName(realm); - ApplicationModel realmAdminApp = realm.getApplicationByName(realmAdminApplicationName); + String realmAdminApplicationClientId = getRealmAdminClientId(realm); + ClientModel realmAdminApp = realm.getClientByClientId(realmAdminApplicationClientId); adminRole = realmAdminApp.getRole(AdminRoles.REALM_ADMIN); } adminConsole.addScopeMapping(adminRole); } - public String getRealmAdminApplicationName(RealmModel realm) { + public String getRealmAdminClientId(RealmModel realm) { return "realm-management"; } - public String getRealmAdminApplicationName(RealmRepresentation realm) { + public String getRealmAdminClientId(RealmRepresentation realm) { return "realm-management"; } @@ -140,7 +139,7 @@ public class RealmManager { boolean removed = model.removeRealm(realm.getId()); if (removed) { - new ApplicationManager(this).removeApplication(getKeycloakAdminstrationRealm(), realm.getMasterAdminApp()); + new ClientManager(this).removeClient(getKeycloakAdminstrationRealm(), realm.getMasterAdminClient()); UserSessionProvider sessions = session.sessions(); if (sessions != null) { @@ -175,20 +174,20 @@ public class RealmManager { private void setupRealmAdminManagement(RealmModel realm) { if (realm.getName().equals(Config.getAdminRealm())) { return; } // don't need to do this for master realm - ApplicationManager applicationManager = new ApplicationManager(new RealmManager(session)); + ClientManager clientManager = new ClientManager(new RealmManager(session)); - String realmAdminApplicationName = getRealmAdminApplicationName(realm); - ApplicationModel realmAdminApp = realm.getApplicationByName(realmAdminApplicationName); - if (realmAdminApp == null) { - realmAdminApp = applicationManager.createApplication(realm, realmAdminApplicationName); + String realmAdminClientId = getRealmAdminClientId(realm); + ClientModel realmAdminClient = realm.getClientByClientId(realmAdminClientId); + if (realmAdminClient == null) { + realmAdminClient = clientManager.createClient(realm, realmAdminClientId); } - RoleModel adminRole = realmAdminApp.addRole(AdminRoles.REALM_ADMIN); - adminRole.setDescription("${role_"+AdminRoles.REALM_ADMIN+"}"); - realmAdminApp.setBearerOnly(true); - realmAdminApp.setFullScopeAllowed(false); + RoleModel adminRole = realmAdminClient.addRole(AdminRoles.REALM_ADMIN); + adminRole.setDescription("${role_" + AdminRoles.REALM_ADMIN + "}"); + realmAdminClient.setBearerOnly(true); + realmAdminClient.setFullScopeAllowed(false); for (String r : AdminRoles.ALL_REALM_ROLES) { - RoleModel role = realmAdminApp.addRole(r); + RoleModel role = realmAdminClient.addRole(r); role.setDescription("${role_"+r+"}"); adminRole.addCompositeRole(role); } @@ -196,19 +195,19 @@ public class RealmManager { private void setupAccountManagement(RealmModel realm) { - ApplicationModel application = realm.getApplicationNameMap().get(Constants.ACCOUNT_MANAGEMENT_APP); - if (application == null) { - application = new ApplicationManager(this).createApplication(realm, Constants.ACCOUNT_MANAGEMENT_APP); - application.setEnabled(true); - application.setFullScopeAllowed(false); + ClientModel client = realm.getClientNameMap().get(Constants.ACCOUNT_MANAGEMENT_CLIENT_ID); + if (client == null) { + client = new ClientManager(this).createClient(realm, Constants.ACCOUNT_MANAGEMENT_CLIENT_ID); + client.setEnabled(true); + client.setFullScopeAllowed(false); String base = contextPath + "/realms/" + realm.getName() + "/account"; String redirectUri = base + "/*"; - application.addRedirectUri(redirectUri); - application.setBaseUrl(base); + client.addRedirectUri(redirectUri); + client.setBaseUrl(base); for (String role : AccountRoles.ALL) { - application.addDefaultRole(role); - application.getRole(role).setDescription("${role_"+role+"}"); + client.addDefaultRole(role); + client.getRole(role).setDescription("${role_"+role+"}"); } } } @@ -225,9 +224,9 @@ public class RealmManager { setupRealmDefaults(realm); setupMasterAdminManagement(realm); - if (!hasRealmAdminManagementApp(rep)) setupRealmAdminManagement(realm); - if (!hasAccountManagementApp(rep)) setupAccountManagement(realm); - if (!hasAdminConsoleApp(rep)) setupAdminConsole(realm); + if (!hasRealmAdminManagementClient(rep)) setupRealmAdminManagement(realm); + if (!hasAccountManagementClient(rep)) setupAccountManagement(realm); + if (!hasAdminConsoleClient(rep)) setupAdminConsole(realm); RepresentationToModel.importRealm(session, rep, realm); @@ -240,30 +239,30 @@ public class RealmManager { return realm; } - private boolean hasRealmAdminManagementApp(RealmRepresentation rep) { - if (rep.getApplications() == null) return false; - for (ApplicationRepresentation app : rep.getApplications()) { - if (app.getName().equals(getRealmAdminApplicationName(rep))) { + private boolean hasRealmAdminManagementClient(RealmRepresentation rep) { + if (rep.getClients() == null) return false; + for (ClientRepresentation clientRep : rep.getClients()) { + if (clientRep.getClientId().equals(getRealmAdminClientId(rep))) { return true; } } return false; } - private boolean hasAccountManagementApp(RealmRepresentation rep) { - if (rep.getApplications() == null) return false; - for (ApplicationRepresentation app : rep.getApplications()) { - if (app.getName().equals(Constants.ACCOUNT_MANAGEMENT_APP)) { + private boolean hasAccountManagementClient(RealmRepresentation rep) { + if (rep.getClients() == null) return false; + for (ClientRepresentation clientRep : rep.getClients()) { + if (clientRep.getClientId().equals(Constants.ACCOUNT_MANAGEMENT_CLIENT_ID)) { return true; } } return false; } - private boolean hasAdminConsoleApp(RealmRepresentation rep) { - if (rep.getApplications() == null) return false; - for (ApplicationRepresentation app : rep.getApplications()) { - if (app.getName().equals(Constants.ADMIN_CONSOLE_APPLICATION)) { + private boolean hasAdminConsoleClient(RealmRepresentation rep) { + if (rep.getClients() == null) return false; + for (ClientRepresentation clientRep : rep.getClients()) { + if (clientRep.getClientId().equals(Constants.ADMIN_CONSOLE_CLIENT_ID)) { return true; } } diff --git a/services/src/main/java/org/keycloak/services/managers/ResourceAdminManager.java b/services/src/main/java/org/keycloak/services/managers/ResourceAdminManager.java index 1bd7fdc30e..ac64cbc5b0 100755 --- a/services/src/main/java/org/keycloak/services/managers/ResourceAdminManager.java +++ b/services/src/main/java/org/keycloak/services/managers/ResourceAdminManager.java @@ -7,7 +7,6 @@ import org.jboss.resteasy.client.ClientResponse; import org.jboss.resteasy.client.core.executors.ApacheHttpClient4Executor; import org.keycloak.TokenIdGenerator; import org.keycloak.constants.AdapterConstants; -import org.keycloak.models.ApplicationModel; import org.keycloak.models.ClientModel; import org.keycloak.models.ClientSessionModel; import org.keycloak.models.KeycloakSession; @@ -43,7 +42,7 @@ import java.util.Set; */ public class ResourceAdminManager { protected static Logger logger = Logger.getLogger(ResourceAdminManager.class); - private static final String APPLICATION_SESSION_HOST_PROPERTY = "${application.session.host}"; + private static final String CLIENT_SESSION_HOST_PROPERTY = "${application.session.host}"; public static ApacheHttpClient4Executor createExecutor() { HttpClient client = new HttpClientBuilder() @@ -58,13 +57,13 @@ public class ResourceAdminManager { } - public static String getManagementUrl(URI requestUri, ApplicationModel application) { - String mgmtUrl = application.getManagementUrl(); + public static String getManagementUrl(URI requestUri, ClientModel client) { + String mgmtUrl = client.getManagementUrl(); if (mgmtUrl == null || mgmtUrl.equals("")) { return null; } - // this is to support relative admin urls when keycloak and applications are deployed on the same machine + // this is to support relative admin urls when keycloak and clients are deployed on the same machine String absoluteURI = ResolveRelative.resolveRelativeUri(requestUri, mgmtUrl); // this is for resolving URI like "http://${jboss.host.name}:8080/..." in order to send request to same machine and avoid request to LB in cluster environment @@ -73,13 +72,13 @@ public class ResourceAdminManager { // For non-cluster setup, return just single configured managementUrls // For cluster setup, return the management Urls corresponding to all registered cluster nodes - private List getAllManagementUrls(URI requestUri, ApplicationModel application) { - String baseMgmtUrl = getManagementUrl(requestUri, application); + private List getAllManagementUrls(URI requestUri, ClientModel client) { + String baseMgmtUrl = getManagementUrl(requestUri, client); if (baseMgmtUrl == null) { return Collections.emptyList(); } - Set registeredNodesHosts = new ApplicationManager().validateRegisteredNodes(application); + Set registeredNodesHosts = new ClientManager().validateRegisteredNodes(client); // No-cluster setup if (registeredNodesHosts.isEmpty()) { @@ -106,7 +105,7 @@ public class ResourceAdminManager { try { // Map from "app" to clientSessions for this app - MultivaluedHashMap clientSessions = new MultivaluedHashMap(); + MultivaluedHashMap clientSessions = new MultivaluedHashMap(); for (UserSessionModel userSession : userSessions) { putClientSessions(clientSessions, userSession); } @@ -114,7 +113,7 @@ public class ResourceAdminManager { logger.debugv("logging out {0} resources ", clientSessions.size()); //logger.infov("logging out resources: {0}", clientSessions); - for (Map.Entry> entry : clientSessions.entrySet()) { + for (Map.Entry> entry : clientSessions.entrySet()) { logoutClientSessions(requestUri, realm, entry.getKey(), entry.getValue(), executor); } } finally { @@ -122,23 +121,21 @@ public class ResourceAdminManager { } } - private void putClientSessions(MultivaluedHashMap clientSessions, UserSessionModel userSession) { + private void putClientSessions(MultivaluedHashMap clientSessions, UserSessionModel userSession) { for (ClientSessionModel clientSession : userSession.getClientSessions()) { ClientModel client = clientSession.getClient(); - if (client instanceof ApplicationModel) { - clientSessions.add((ApplicationModel)client, clientSession); - } + clientSessions.add(client, clientSession); } } - public void logoutUserFromApplication(URI requestUri, RealmModel realm, ApplicationModel resource, UserModel user, KeycloakSession session) { + public void logoutUserFromClient(URI requestUri, RealmModel realm, ClientModel resource, UserModel user, KeycloakSession session) { ApacheHttpClient4Executor executor = createExecutor(); try { List userSessions = session.sessions().getUserSessions(realm, user); List ourAppClientSessions = null; if (userSessions != null) { - MultivaluedHashMap clientSessions = new MultivaluedHashMap(); + MultivaluedHashMap clientSessions = new MultivaluedHashMap(); for (UserSessionModel userSession : userSessions) { putClientSessions(clientSessions, userSession); } @@ -152,11 +149,11 @@ public class ResourceAdminManager { } - public boolean logoutClientSession(URI requestUri, RealmModel realm, ApplicationModel resource, ClientSessionModel clientSession, ApacheHttpClient4Executor client) { + public boolean logoutClientSession(URI requestUri, RealmModel realm, ClientModel resource, ClientSessionModel clientSession, ApacheHttpClient4Executor client) { return logoutClientSessions(requestUri, realm, resource, Arrays.asList(clientSession), client); } - protected boolean logoutClientSessions(URI requestUri, RealmModel realm, ApplicationModel resource, List clientSessions, ApacheHttpClient4Executor client) { + protected boolean logoutClientSessions(URI requestUri, RealmModel realm, ClientModel resource, List clientSessions, ApacheHttpClient4Executor client) { String managementUrl = getManagementUrl(requestUri, resource); if (managementUrl != null) { @@ -166,9 +163,9 @@ public class ResourceAdminManager { if (clientSessions != null && clientSessions.size() > 0) { adapterSessionIds = new MultivaluedHashMap(); for (ClientSessionModel clientSession : clientSessions) { - String adapterSessionId = clientSession.getNote(AdapterConstants.APPLICATION_SESSION_STATE); + String adapterSessionId = clientSession.getNote(AdapterConstants.CLIENT_SESSION_STATE); if (adapterSessionId != null) { - String host = clientSession.getNote(AdapterConstants.APPLICATION_SESSION_HOST); + String host = clientSession.getNote(AdapterConstants.CLIENT_SESSION_HOST); adapterSessionIds.add(host, adapterSessionId); } if (clientSession.getUserSession() != null) userSessions.add(clientSession.getUserSession().getId()); @@ -176,17 +173,17 @@ public class ResourceAdminManager { } if (adapterSessionIds == null || adapterSessionIds.isEmpty()) { - logger.debugv("Can't logout {0}: no logged adapter sessions", resource.getName()); + logger.debugv("Can't logout {0}: no logged adapter sessions", resource.getClientId()); return false; } - if (managementUrl.contains(APPLICATION_SESSION_HOST_PROPERTY)) { + if (managementUrl.contains(CLIENT_SESSION_HOST_PROPERTY)) { boolean allPassed = true; // Send logout separately to each host (needed for single-sign-out in cluster for non-distributable apps - KEYCLOAK-748) for (Map.Entry> entry : adapterSessionIds.entrySet()) { String host = entry.getKey(); List sessionIds = entry.getValue(); - String currentHostMgmtUrl = managementUrl.replace(APPLICATION_SESSION_HOST_PROPERTY, host); + String currentHostMgmtUrl = managementUrl.replace(CLIENT_SESSION_HOST_PROPERTY, host); allPassed = sendLogoutRequest(realm, resource, sessionIds, userSessions, client, 0, currentHostMgmtUrl) && allPassed; } @@ -201,7 +198,7 @@ public class ResourceAdminManager { return sendLogoutRequest(realm, resource, allSessionIds, userSessions, client, 0, managementUrl); } } else { - logger.debugv("Can't logout {0}: no management url", resource.getName()); + logger.debugv("Can't logout {0}: no management url", resource.getClientId()); return false; } } @@ -213,12 +210,12 @@ public class ResourceAdminManager { try { realm.setNotBefore(Time.currentTime()); - List resources = realm.getApplications(); + List resources = realm.getClients(); logger.debugv("logging out {0} resources ", resources.size()); GlobalRequestResult finalResult = new GlobalRequestResult(); - for (ApplicationModel resource : resources) { - GlobalRequestResult currentResult = logoutApplication(requestUri, realm, resource, executor, realm.getNotBefore()); + for (ClientModel resource : resources) { + GlobalRequestResult currentResult = logoutClient(requestUri, realm, resource, executor, realm.getNotBefore()); finalResult.addAll(currentResult); } return finalResult; @@ -227,25 +224,25 @@ public class ResourceAdminManager { } } - public GlobalRequestResult logoutApplication(URI requestUri, RealmModel realm, ApplicationModel resource) { + public GlobalRequestResult logoutClient(URI requestUri, RealmModel realm, ClientModel resource) { ApacheHttpClient4Executor executor = createExecutor(); try { resource.setNotBefore(Time.currentTime()); - return logoutApplication(requestUri, realm, resource, executor, resource.getNotBefore()); + return logoutClient(requestUri, realm, resource, executor, resource.getNotBefore()); } finally { executor.getHttpClient().getConnectionManager().shutdown(); } } - protected GlobalRequestResult logoutApplication(URI requestUri, RealmModel realm, ApplicationModel resource, ApacheHttpClient4Executor executor, int notBefore) { + protected GlobalRequestResult logoutClient(URI requestUri, RealmModel realm, ClientModel resource, ApacheHttpClient4Executor executor, int notBefore) { List mgmtUrls = getAllManagementUrls(requestUri, resource); if (mgmtUrls.isEmpty()) { - logger.debug("No management URL or no registered cluster nodes for the application " + resource.getName()); + logger.debug("No management URL or no registered cluster nodes for the client " + resource.getClientId()); return new GlobalRequestResult(); } - if (logger.isDebugEnabled()) logger.debug("Send logoutApplication for URLs: " + mgmtUrls); + if (logger.isDebugEnabled()) logger.debug("Send logoutClient for URLs: " + mgmtUrls); // Propagate this to all hosts GlobalRequestResult result = new GlobalRequestResult(); @@ -259,16 +256,16 @@ public class ResourceAdminManager { return result; } - protected boolean sendLogoutRequest(RealmModel realm, ApplicationModel resource, List adapterSessionIds, List userSessions, ApacheHttpClient4Executor client, int notBefore, String managementUrl) { - LogoutAction adminAction = new LogoutAction(TokenIdGenerator.generateId(), Time.currentTime() + 30, resource.getName(), adapterSessionIds, notBefore, userSessions); + protected boolean sendLogoutRequest(RealmModel realm, ClientModel resource, List adapterSessionIds, List userSessions, ApacheHttpClient4Executor client, int notBefore, String managementUrl) { + LogoutAction adminAction = new LogoutAction(TokenIdGenerator.generateId(), Time.currentTime() + 30, resource.getClientId(), adapterSessionIds, notBefore, userSessions); String token = new TokenManager().encodeToken(realm, adminAction); - if (logger.isDebugEnabled()) logger.debugv("logout resource {0} url: {1} sessionIds: " + adapterSessionIds, resource.getName(), managementUrl); + if (logger.isDebugEnabled()) logger.debugv("logout resource {0} url: {1} sessionIds: " + adapterSessionIds, resource.getClientId(), managementUrl); ClientRequest request = client.createRequest(UriBuilder.fromUri(managementUrl).path(AdapterConstants.K_LOGOUT).build().toString()); ClientResponse response; try { response = request.body(MediaType.TEXT_PLAIN_TYPE, token).post(); } catch (Exception e) { - logger.warn("Logout for application '" + resource.getName() + "' failed", e); + logger.warn("Logout for client '" + resource.getClientId() + "' failed", e); return false; } try { @@ -285,8 +282,8 @@ public class ResourceAdminManager { try { GlobalRequestResult finalResult = new GlobalRequestResult(); - for (ApplicationModel application : realm.getApplications()) { - GlobalRequestResult currentResult = pushRevocationPolicy(requestUri, realm, application, realm.getNotBefore(), executor); + for (ClientModel client : realm.getClients()) { + GlobalRequestResult currentResult = pushRevocationPolicy(requestUri, realm, client, realm.getNotBefore(), executor); finalResult.addAll(currentResult); } return finalResult; @@ -295,21 +292,21 @@ public class ResourceAdminManager { } } - public GlobalRequestResult pushApplicationRevocationPolicy(URI requestUri, RealmModel realm, ApplicationModel application) { + public GlobalRequestResult pushClientRevocationPolicy(URI requestUri, RealmModel realm, ClientModel client) { ApacheHttpClient4Executor executor = createExecutor(); try { - return pushRevocationPolicy(requestUri, realm, application, application.getNotBefore(), executor); + return pushRevocationPolicy(requestUri, realm, client, client.getNotBefore(), executor); } finally { executor.getHttpClient().getConnectionManager().shutdown(); } } - protected GlobalRequestResult pushRevocationPolicy(URI requestUri, RealmModel realm, ApplicationModel resource, int notBefore, ApacheHttpClient4Executor executor) { + protected GlobalRequestResult pushRevocationPolicy(URI requestUri, RealmModel realm, ClientModel resource, int notBefore, ApacheHttpClient4Executor executor) { List mgmtUrls = getAllManagementUrls(requestUri, resource); if (mgmtUrls.isEmpty()) { - logger.debugf("No management URL or no registered cluster nodes for the application %s", resource.getName()); + logger.debugf("No management URL or no registered cluster nodes for the client %s", resource.getClientId()); return new GlobalRequestResult(); } @@ -327,10 +324,10 @@ public class ResourceAdminManager { return result; } - protected boolean sendPushRevocationPolicyRequest(RealmModel realm, ApplicationModel resource, int notBefore, ApacheHttpClient4Executor client, String managementUrl) { - PushNotBeforeAction adminAction = new PushNotBeforeAction(TokenIdGenerator.generateId(), Time.currentTime() + 30, resource.getName(), notBefore); + protected boolean sendPushRevocationPolicyRequest(RealmModel realm, ClientModel resource, int notBefore, ApacheHttpClient4Executor client, String managementUrl) { + PushNotBeforeAction adminAction = new PushNotBeforeAction(TokenIdGenerator.generateId(), Time.currentTime() + 30, resource.getClientId(), notBefore); String token = new TokenManager().encodeToken(realm, adminAction); - logger.infov("pushRevocation resource: {0} url: {1}", resource.getName(), managementUrl); + logger.infov("pushRevocation resource: {0} url: {1}", resource.getClientId(), managementUrl); ClientRequest request = client.createRequest(UriBuilder.fromUri(managementUrl).path(AdapterConstants.K_PUSH_NOT_BEFORE).build().toString()); ClientResponse response; try { @@ -348,10 +345,10 @@ public class ResourceAdminManager { } } - public GlobalRequestResult testNodesAvailability(URI requestUri, RealmModel realm, ApplicationModel application) { - List mgmtUrls = getAllManagementUrls(requestUri, application); + public GlobalRequestResult testNodesAvailability(URI requestUri, RealmModel realm, ClientModel client) { + List mgmtUrls = getAllManagementUrls(requestUri, client); if (mgmtUrls.isEmpty()) { - logger.debug("No management URL or no registered cluster nodes for the application " + application.getName()); + logger.debug("No management URL or no registered cluster nodes for the application " + client.getClientId()); return new GlobalRequestResult(); } @@ -363,7 +360,7 @@ public class ResourceAdminManager { // Propagate this to all hosts GlobalRequestResult result = new GlobalRequestResult(); for (String mgmtUrl : mgmtUrls) { - if (sendTestNodeAvailabilityRequest(realm, application, executor, mgmtUrl)) { + if (sendTestNodeAvailabilityRequest(realm, client, executor, mgmtUrl)) { result.addSuccessRequest(mgmtUrl); } else { result.addFailedRequest(mgmtUrl); @@ -375,11 +372,11 @@ public class ResourceAdminManager { } } - protected boolean sendTestNodeAvailabilityRequest(RealmModel realm, ApplicationModel application, ApacheHttpClient4Executor client, String managementUrl) { - TestAvailabilityAction adminAction = new TestAvailabilityAction(TokenIdGenerator.generateId(), Time.currentTime() + 30, application.getName()); + protected boolean sendTestNodeAvailabilityRequest(RealmModel realm, ClientModel client, ApacheHttpClient4Executor httpClient, String managementUrl) { + TestAvailabilityAction adminAction = new TestAvailabilityAction(TokenIdGenerator.generateId(), Time.currentTime() + 30, client.getClientId()); String token = new TokenManager().encodeToken(realm, adminAction); - logger.debugv("testNodes availability resource: {0} url: {1}", application.getName(), managementUrl); - ClientRequest request = client.createRequest(UriBuilder.fromUri(managementUrl).path(AdapterConstants.K_TEST_AVAILABLE).build().toString()); + logger.debugv("testNodes availability resource: {0} url: {1}", client.getClientId(), managementUrl); + ClientRequest request = httpClient.createRequest(UriBuilder.fromUri(managementUrl).path(AdapterConstants.K_TEST_AVAILABLE).build().toString()); ClientResponse response; try { response = request.body(MediaType.TEXT_PLAIN_TYPE, token).post(); diff --git a/services/src/main/java/org/keycloak/services/resources/AccountService.java b/services/src/main/java/org/keycloak/services/resources/AccountService.java index 906e3e2cdc..71fb570adb 100755 --- a/services/src/main/java/org/keycloak/services/resources/AccountService.java +++ b/services/src/main/java/org/keycloak/services/resources/AccountService.java @@ -131,16 +131,16 @@ public class AccountService { private KeycloakSession session; private final AppAuthManager authManager; - private final ApplicationModel application; + private final ClientModel client; private EventBuilder event; private AccountProvider account; private Auth auth; private EventStoreProvider eventStore; private String stateChecker; - public AccountService(RealmModel realm, ApplicationModel application, EventBuilder event) { + public AccountService(RealmModel realm, ClientModel client, EventBuilder event) { this.realm = realm; - this.application = application; + this.client = client; this.event = event; this.authManager = new AppAuthManager(); } @@ -152,11 +152,11 @@ public class AccountService { AuthenticationManager.AuthResult authResult = authManager.authenticateBearerToken(session, realm, uriInfo, clientConnection, headers); if (authResult != null) { - auth = new Auth(realm, authResult.getToken(), authResult.getUser(), application, authResult.getSession(), false); + auth = new Auth(realm, authResult.getToken(), authResult.getUser(), client, authResult.getSession(), false); } else { authResult = authManager.authenticateIdentityCookie(session, realm, uriInfo, clientConnection, headers); if (authResult != null) { - auth = new Auth(realm, authResult.getToken(), authResult.getUser(), application, authResult.getSession(), true); + auth = new Auth(realm, authResult.getToken(), authResult.getUser(), client, authResult.getSession(), true); Cookie cookie = headers.getCookies().get(KEYCLOAK_STATE_CHECKER); if (cookie != null) { stateChecker = cookie.getValue(); @@ -193,14 +193,14 @@ public class AccountService { if (userSession != null) { boolean associated = false; for (ClientSessionModel c : userSession.getClientSessions()) { - if (c.getClient().equals(application)) { + if (c.getClient().equals(client)) { auth.setClientSession(c); associated = true; break; } } if (!associated) { - ClientSessionModel clientSession = session.sessions().createClientSession(realm, application); + ClientSessionModel clientSession = session.sessions().createClientSession(realm, client); clientSession.setUserSession(userSession); auth.setClientSession(clientSession); } @@ -737,7 +737,7 @@ public class AccountService { logger.debug("realm not enabled"); throw new ForbiddenException(); } - if (!application.isEnabled()) { + if (!client.isEnabled()) { logger.debug("account management app not enabled"); throw new ForbiddenException(); } @@ -766,7 +766,7 @@ public class AccountService { String authUrl = OIDCLoginProtocolService.authUrl(uriInfo).build(realm.getName()).toString(); oauth.setAuthUrl(authUrl); - oauth.setClientId(Constants.ACCOUNT_MANAGEMENT_APP); + oauth.setClientId(Constants.ACCOUNT_MANAGEMENT_CLIENT_ID); UriBuilder uriBuilder = Urls.accountPageBuilder(uriInfo.getBaseUri()).path(AccountService.class, "loginRedirect"); @@ -813,21 +813,21 @@ public class AccountService { String referrerUri = uriInfo.getQueryParameters().getFirst("referrer_uri"); - ApplicationModel application = realm.getApplicationByName(referrer); - if (application != null) { + ClientModel referrerClient = realm.getClientByClientId(referrer); + if (referrerClient != null) { if (referrerUri != null) { - referrerUri = RedirectUtils.verifyRedirectUri(uriInfo, referrerUri, realm, application); + referrerUri = RedirectUtils.verifyRedirectUri(uriInfo, referrerUri, realm, referrerClient); } else { - referrerUri = ResolveRelative.resolveRelativeUri(uriInfo.getRequestUri(), application.getBaseUrl()); + referrerUri = ResolveRelative.resolveRelativeUri(uriInfo.getRequestUri(), referrerClient.getBaseUrl()); } if (referrerUri != null) { return new String[]{referrer, referrerUri}; } } else if (referrerUri != null) { - ClientModel client = realm.getOAuthClient(referrer); + referrerClient = realm.getClientByClientId(referrer); if (client != null) { - referrerUri = RedirectUtils.verifyRedirectUri(uriInfo, referrerUri, realm, application); + referrerUri = RedirectUtils.verifyRedirectUri(uriInfo, referrerUri, realm, referrerClient); if (referrerUri != null) { return new String[]{referrer, referrerUri}; @@ -843,7 +843,7 @@ public class AccountService { throw new ForbiddenException(); } - if (!auth.hasAppRole(application, role)) { + if (!auth.hasClientRole(client, role)) { throw new ForbiddenException(); } } @@ -853,7 +853,7 @@ public class AccountService { throw new ForbiddenException(); } - if (!auth.hasOneOfAppRole(application, roles)) { + if (!auth.hasOneOfAppRole(client, roles)) { throw new ForbiddenException(); } } diff --git a/services/src/main/java/org/keycloak/services/resources/ClientsManagementService.java b/services/src/main/java/org/keycloak/services/resources/ClientsManagementService.java index 1761138677..1eb54800a4 100755 --- a/services/src/main/java/org/keycloak/services/resources/ClientsManagementService.java +++ b/services/src/main/java/org/keycloak/services/resources/ClientsManagementService.java @@ -1,20 +1,5 @@ package org.keycloak.services.resources; -import java.util.HashMap; -import java.util.Map; - -import javax.ws.rs.HeaderParam; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; -import javax.ws.rs.core.Context; -import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.MultivaluedMap; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.UriBuilder; -import javax.ws.rs.core.UriInfo; -import javax.ws.rs.ext.Providers; - import org.jboss.logging.Logger; import org.jboss.resteasy.spi.BadRequestException; import org.jboss.resteasy.spi.HttpRequest; @@ -26,15 +11,28 @@ import org.keycloak.events.Details; import org.keycloak.events.Errors; import org.keycloak.events.EventBuilder; import org.keycloak.events.EventType; -import org.keycloak.models.ApplicationModel; import org.keycloak.models.ClientModel; import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; -import org.keycloak.protocol.oidc.OIDCLoginProtocolService; import org.keycloak.protocol.oidc.utils.AuthorizeClientUtil; import org.keycloak.services.ForbiddenException; import org.keycloak.util.Time; +import javax.ws.rs.HeaderParam; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriBuilder; +import javax.ws.rs.core.UriInfo; +import javax.ws.rs.ext.Providers; +import java.util.HashMap; +import java.util.Map; + /** * @author Marek Posolda */ @@ -84,7 +82,7 @@ public class ClientsManagementService { } /** - * URL invoked by adapter to register new application cluster node. Each application cluster node will invoke this URL once it joins cluster + * URL invoked by adapter to register new client cluster node. Each application cluster node will invoke this URL once it joins cluster * * @param authorizationHeader * @param formData @@ -92,7 +90,7 @@ public class ClientsManagementService { */ @Path("register-node") @POST - @Produces("application/json") + @Produces(MediaType.APPLICATION_JSON) public Response registerNode(@HeaderParam(HttpHeaders.AUTHORIZATION) String authorizationHeader, final MultivaluedMap formData) { if (!checkSsl()) { throw new ForbiddenException("HTTPS required"); @@ -105,13 +103,13 @@ public class ClientsManagementService { throw new UnauthorizedException("Realm not enabled"); } - ApplicationModel application = authorizeApplication(authorizationHeader, formData); - String nodeHost = getApplicationClusterHost(formData); + ClientModel client = authorizeClient(authorizationHeader, formData); + String nodeHost = getClientClusterHost(formData); - event.client(application).detail(Details.NODE_HOST, nodeHost); - logger.debugf("Registering cluster host '%s' for client '%s'", nodeHost, application.getName()); + event.client(client).detail(Details.NODE_HOST, nodeHost); + logger.debugf("Registering cluster host '%s' for client '%s'", nodeHost, client.getClientId()); - application.registerNode(nodeHost, Time.currentTime()); + client.registerNode(nodeHost, Time.currentTime()); event.success(); @@ -120,7 +118,7 @@ public class ClientsManagementService { /** - * URL invoked by adapter to register new application cluster node. Each application cluster node will invoke this URL once it joins cluster + * URL invoked by adapter to register new client cluster node. Each application cluster node will invoke this URL once it joins cluster * * @param authorizationHeader * @param formData @@ -128,7 +126,7 @@ public class ClientsManagementService { */ @Path("unregister-node") @POST - @Produces("application/json") + @Produces(MediaType.APPLICATION_JSON) public Response unregisterNode(@HeaderParam(HttpHeaders.AUTHORIZATION) String authorizationHeader, final MultivaluedMap formData) { if (!checkSsl()) { throw new ForbiddenException("HTTPS required"); @@ -141,20 +139,20 @@ public class ClientsManagementService { throw new UnauthorizedException("Realm not enabled"); } - ApplicationModel application = authorizeApplication(authorizationHeader, formData); - String nodeHost = getApplicationClusterHost(formData); + ClientModel client = authorizeClient(authorizationHeader, formData); + String nodeHost = getClientClusterHost(formData); - event.client(application).detail(Details.NODE_HOST, nodeHost); - logger.debugf("Unregistering cluster host '%s' for client '%s'", nodeHost, application.getName()); + event.client(client).detail(Details.NODE_HOST, nodeHost); + logger.debugf("Unregistering cluster host '%s' for client '%s'", nodeHost, client.getClientId()); - application.unregisterNode(nodeHost); + client.unregisterNode(nodeHost); event.success(); return Response.noContent().build(); } - protected ApplicationModel authorizeApplication(String authorizationHeader, MultivaluedMap formData) { + protected ClientModel authorizeClient(String authorizationHeader, MultivaluedMap formData) { ClientModel client = AuthorizeClientUtil.authorizeClient(authorizationHeader, formData, event, realm); if (client.isPublicClient()) { @@ -162,31 +160,23 @@ public class ClientsManagementService { error.put(OAuth2Constants.ERROR, "invalid_client"); error.put(OAuth2Constants.ERROR_DESCRIPTION, "Public clients not allowed"); event.error(Errors.INVALID_CLIENT); - throw new BadRequestException("Public clients not allowed", javax.ws.rs.core.Response.status(javax.ws.rs.core.Response.Status.BAD_REQUEST).entity(error).type("application/json").build()); + throw new BadRequestException("Public clients not allowed", javax.ws.rs.core.Response.status(javax.ws.rs.core.Response.Status.BAD_REQUEST).entity(error).type(MediaType.APPLICATION_JSON_TYPE).build()); } - if (!(client instanceof ApplicationModel)) { - Map error = new HashMap(); - error.put(OAuth2Constants.ERROR, "invalid_client"); - error.put(OAuth2Constants.ERROR_DESCRIPTION, "Just applications are allowed"); - event.error(Errors.INVALID_CLIENT); - throw new BadRequestException("ust applications are allowed", javax.ws.rs.core.Response.status(javax.ws.rs.core.Response.Status.BAD_REQUEST).entity(error).type("application/json").build()); - } - - return (ApplicationModel)client; + return client; } - protected String getApplicationClusterHost(MultivaluedMap formData) { - String applicationClusterHost = formData.getFirst(AdapterConstants.APPLICATION_CLUSTER_HOST); - if (applicationClusterHost == null || applicationClusterHost.length() == 0) { + protected String getClientClusterHost(MultivaluedMap formData) { + String clientClusterHost = formData.getFirst(AdapterConstants.CLIENT_CLUSTER_HOST); + if (clientClusterHost == null || clientClusterHost.length() == 0) { Map error = new HashMap(); error.put(OAuth2Constants.ERROR, "invalid_request"); - error.put(OAuth2Constants.ERROR_DESCRIPTION, "application cluster host not specified"); + error.put(OAuth2Constants.ERROR_DESCRIPTION, "Client cluster host not specified"); event.error(Errors.INVALID_CODE); - throw new BadRequestException("Cluster host not specified", javax.ws.rs.core.Response.status(javax.ws.rs.core.Response.Status.BAD_REQUEST).entity(error).type("application/json").build()); + throw new BadRequestException("Cluster host not specified", javax.ws.rs.core.Response.status(javax.ws.rs.core.Response.Status.BAD_REQUEST).entity(error).type(MediaType.APPLICATION_JSON_TYPE).build()); } - return applicationClusterHost; + return clientClusterHost; } diff --git a/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java b/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java index 89ce7cc587..4098d33e4f 100755 --- a/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java +++ b/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java @@ -36,7 +36,6 @@ import org.keycloak.models.ClientSessionModel; import org.keycloak.models.FederatedIdentityModel; import org.keycloak.models.IdentityProviderModel; import org.keycloak.models.KeycloakSession; -import org.keycloak.models.OAuthClientModel; import org.keycloak.models.RealmModel; import org.keycloak.models.UserModel; import org.keycloak.models.UserSessionModel; @@ -75,7 +74,7 @@ import java.util.Map; import static org.keycloak.models.AccountRoles.MANAGE_ACCOUNT; import static org.keycloak.models.ClientSessionModel.Action.AUTHENTICATE; -import static org.keycloak.models.Constants.ACCOUNT_MANAGEMENT_APP; +import static org.keycloak.models.Constants.ACCOUNT_MANAGEMENT_CLIENT_ID; import static org.keycloak.models.UserModel.RequiredAction.UPDATE_PROFILE; /** @@ -181,7 +180,7 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal if (authResult != null) { String audience = authResult.getToken().getAudience(); - ClientModel clientModel = this.realmModel.findClient(audience); + ClientModel clientModel = this.realmModel.getClientByClientId(audience); if (clientModel == null) { return badRequest("Invalid client."); @@ -191,7 +190,7 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal return corsResponse(badRequest("Client [" + audience + "] not authorized to retrieve tokens from identity provider [" + providerId + "]."), clientModel); } - if (OAuthClientModel.class.isInstance(clientModel) && !forceRetrieval) { + if (clientModel.isConsentRequired()) { return corsResponse(Flows.forms(this.session, this.realmModel, clientModel, this.uriInfo, headers) .setClientSessionCode(authManager.extractAuthorizationHeaderToken(this.request.getHttpHeaders())) .setAccessRequest("Your information from " + providerId + " identity provider.") @@ -323,7 +322,7 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal return redirectToErrorPage(Messages.ACCOUNT_DISABLED); } - if (!authenticatedUser.hasRole(this.realmModel.getApplicationByName(ACCOUNT_MANAGEMENT_APP).getRole(MANAGE_ACCOUNT))) { + if (!authenticatedUser.hasRole(this.realmModel.getClientByClientId(ACCOUNT_MANAGEMENT_CLIENT_ID).getRole(MANAGE_ACCOUNT))) { fireErrorEvent(Errors.NOT_ALLOWED); return redirectToErrorPage(Messages.INSUFFICIENT_PERMISSION); } @@ -379,7 +378,7 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal return clientCode; } - throw new IdentityBrokerException("Invalid code, please login again through your application."); + throw new IdentityBrokerException("Invalid code, please login again through your client."); } private AuthenticationRequest createAuthenticationRequest(String providerId, ClientSessionCode clientSessionCode) { diff --git a/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java b/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java index 078e408d66..106be1cadc 100755 --- a/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java +++ b/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java @@ -36,7 +36,6 @@ import org.keycloak.models.ClientModel; import org.keycloak.models.ClientSessionModel; import org.keycloak.models.KeycloakSession; import org.keycloak.models.ModelException; -import org.keycloak.models.PasswordPolicy; import org.keycloak.models.RealmModel; import org.keycloak.models.RequiredCredentialModel; import org.keycloak.models.UserCredentialModel; @@ -73,8 +72,6 @@ import javax.ws.rs.core.Response; import javax.ws.rs.core.UriBuilder; import javax.ws.rs.core.UriInfo; import javax.ws.rs.ext.Providers; - -import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.concurrent.TimeUnit; @@ -320,7 +317,6 @@ public class LoginActionsService { event.detail(Details.REMEMBER_ME, "true"); } - ClientModel client = clientSession.getClient(); if (client == null) { event.error(Errors.CLIENT_NOT_FOUND); diff --git a/services/src/main/java/org/keycloak/services/resources/PublicRealmResource.java b/services/src/main/java/org/keycloak/services/resources/PublicRealmResource.java index b4c3284225..25beaa5f14 100755 --- a/services/src/main/java/org/keycloak/services/resources/PublicRealmResource.java +++ b/services/src/main/java/org/keycloak/services/resources/PublicRealmResource.java @@ -14,6 +14,7 @@ import javax.ws.rs.OPTIONS; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; @@ -59,7 +60,7 @@ public class PublicRealmResource { */ @GET @NoCache - @Produces("application/json") + @Produces(MediaType.APPLICATION_JSON) public PublishedRealmRepresentation getRealm() { Cors.add(request).allowedOrigins(Cors.ACCESS_CONTROL_ALLOW_ORIGIN_WILDCARD).auth().build(response); return realmRep(realm, uriInfo); diff --git a/services/src/main/java/org/keycloak/services/resources/RealmsResource.java b/services/src/main/java/org/keycloak/services/resources/RealmsResource.java index daed1e087a..571f111a8f 100755 --- a/services/src/main/java/org/keycloak/services/resources/RealmsResource.java +++ b/services/src/main/java/org/keycloak/services/resources/RealmsResource.java @@ -5,7 +5,7 @@ import org.jboss.resteasy.spi.NotFoundException; import org.jboss.resteasy.spi.ResteasyProviderFactory; import org.keycloak.ClientConnection; import org.keycloak.events.EventBuilder; -import org.keycloak.models.ApplicationModel; +import org.keycloak.models.ClientModel; import org.keycloak.models.Constants; import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; @@ -157,16 +157,15 @@ public class RealmsResource { RealmManager realmManager = new RealmManager(session); RealmModel realm = locateRealm(name, realmManager); - ApplicationModel application = realm.getApplicationNameMap().get(Constants.ACCOUNT_MANAGEMENT_APP); - if (application == null || !application.isEnabled()) { + ClientModel client = realm.getClientNameMap().get(Constants.ACCOUNT_MANAGEMENT_CLIENT_ID); + if (client == null || !client.isEnabled()) { logger.debug("account management not enabled"); throw new NotFoundException("account management not enabled"); } EventBuilder event = new EventBuilder(realm, session, clientConnection); - AccountService accountService = new AccountService(realm, application, event); + AccountService accountService = new AccountService(realm, client, event); ResteasyProviderFactory.getInstance().injectProperties(accountService); - //resourceContext.initResource(accountService); accountService.init(); return accountService; } @@ -177,7 +176,6 @@ public class RealmsResource { RealmModel realm = locateRealm(name, realmManager); PublicRealmResource realmResource = new PublicRealmResource(realm); ResteasyProviderFactory.getInstance().injectProperties(realmResource); - //resourceContext.initResource(realmResource); return realmResource; } @@ -188,7 +186,6 @@ public class RealmsResource { IdentityBrokerService brokerService = new IdentityBrokerService(realm); ResteasyProviderFactory.getInstance().injectProperties(brokerService); - //resourceContext.initResource(brokerService); brokerService.init(); diff --git a/services/src/main/java/org/keycloak/services/resources/admin/AdminAuth.java b/services/src/main/java/org/keycloak/services/resources/admin/AdminAuth.java index ca7dece3e3..3dd1123aa6 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/AdminAuth.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/AdminAuth.java @@ -1,6 +1,5 @@ package org.keycloak.services.resources.admin; -import org.keycloak.models.ApplicationModel; import org.keycloak.models.ClientModel; import org.keycloak.models.RealmModel; import org.keycloak.models.RoleModel; @@ -43,7 +42,7 @@ public class AdminAuth { public boolean hasRealmRole(String role) { - if (client instanceof ApplicationModel) { + if (client instanceof ClientModel) { RoleModel roleModel = realm.getRole(role); return user.hasRole(roleModel) && client.hasScope(roleModel); } else { @@ -61,17 +60,17 @@ public class AdminAuth { return false; } - public boolean hasAppRole(ApplicationModel app, String role) { - if (client instanceof ApplicationModel) { + public boolean hasAppRole(ClientModel app, String role) { + if (client instanceof ClientModel) { RoleModel roleModel = app.getRole(role); return user.hasRole(roleModel) && client.hasScope(roleModel); } else { - AccessToken.Access access = token.getResourceAccess(app.getName()); + AccessToken.Access access = token.getResourceAccess(app.getClientId()); return access != null && access.isUserInRole(role); } } - public boolean hasOneOfAppRole(ApplicationModel app, String... roles) { + public boolean hasOneOfAppRole(ClientModel app, String... roles) { for (String r : roles) { if (hasAppRole(app, r)) { return true; diff --git a/services/src/main/java/org/keycloak/services/resources/admin/AdminConsole.java b/services/src/main/java/org/keycloak/services/resources/admin/AdminConsole.java index 8ed297ad8a..24d76b2873 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/AdminConsole.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/AdminConsole.java @@ -14,7 +14,7 @@ import org.keycloak.freemarker.FreeMarkerUtil; import org.keycloak.freemarker.Theme; import org.keycloak.freemarker.ThemeProvider; import org.keycloak.models.AdminRoles; -import org.keycloak.models.ApplicationModel; +import org.keycloak.models.ClientModel; import org.keycloak.models.Constants; import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; @@ -22,7 +22,7 @@ import org.keycloak.models.RoleModel; import org.keycloak.models.UserModel; import org.keycloak.protocol.oidc.OIDCLoginProtocolService; import org.keycloak.services.managers.AppAuthManager; -import org.keycloak.services.managers.ApplicationManager; +import org.keycloak.services.managers.ClientManager; import org.keycloak.services.managers.AuthenticationManager; import org.keycloak.services.managers.RealmManager; import org.keycloak.services.resources.KeycloakApplication; @@ -151,14 +151,14 @@ public class AdminConsole { */ @Path("config") @GET - @Produces("application/json") + @Produces(MediaType.APPLICATION_JSON) @NoCache - public ApplicationManager.InstallationAdapterConfig config() { - ApplicationModel consoleApp = realm.getApplicationByName(Constants.ADMIN_CONSOLE_APPLICATION); + public ClientManager.InstallationAdapterConfig config() { + ClientModel consoleApp = realm.getClientByClientId(Constants.ADMIN_CONSOLE_CLIENT_ID); if (consoleApp == null) { - throw new NotFoundException("Could not find admin console application"); + throw new NotFoundException("Could not find admin console client"); } - return new ApplicationManager().toInstallationRepresentation(realm, consoleApp, keycloak.getBaseUri(uriInfo)); + return new ClientManager().toInstallationRepresentation(realm, consoleApp, keycloak.getBaseUri(uriInfo)); } @@ -170,7 +170,7 @@ public class AdminConsole { */ @Path("whoami") @GET - @Produces("application/json") + @Produces(MediaType.APPLICATION_JSON) @NoCache public Response whoAmI(final @Context HttpHeaders headers) { RealmManager realmManager = new RealmManager(session); @@ -208,7 +208,7 @@ public class AdminConsole { private void addRealmAccess(RealmModel realm, UserModel user, Map> realmAdminAccess) { RealmManager realmManager = new RealmManager(session); - ApplicationModel realmAdminApp = realm.getApplicationByName(realmManager.getRealmAdminApplicationName(realm)); + ClientModel realmAdminApp = realm.getClientByClientId(realmManager.getRealmAdminClientId(realm)); Set roles = realmAdminApp.getRoles(); for (RoleModel role : roles) { if (!user.hasRole(role)) continue; @@ -223,7 +223,7 @@ public class AdminConsole { private void addMasterRealmAccess(RealmModel masterRealm, UserModel user, Map> realmAdminAccess) { List realms = session.realms().getRealms(); for (RealmModel realm : realms) { - ApplicationModel realmAdminApp = realm.getMasterAdminApp(); + ClientModel realmAdminApp = realm.getMasterAdminClient(); Set roles = realmAdminApp.getRoles(); for (RoleModel role : roles) { if (!user.hasRole(role)) continue; diff --git a/services/src/main/java/org/keycloak/services/resources/admin/AdminRoot.java b/services/src/main/java/org/keycloak/services/resources/admin/AdminRoot.java index c049ac4abe..2ece39b9c6 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/AdminRoot.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/AdminRoot.java @@ -149,7 +149,7 @@ public class AdminRoot { throw new UnauthorizedException("Bearer"); } - ClientModel client = realm.findClient(token.getIssuedFor()); + ClientModel client = realm.getClientByClientId(token.getIssuedFor()); if (client == null) { throw new NotFoundException("Could not find client for authorization"); diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ApplicationsByIdResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ApplicationsByIdResource.java deleted file mode 100755 index fc93f017c3..0000000000 --- a/services/src/main/java/org/keycloak/services/resources/admin/ApplicationsByIdResource.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.keycloak.services.resources.admin; - -import org.keycloak.models.ApplicationModel; -import org.keycloak.models.RealmModel; - -/** - * @author Bill Burke - * @version $Revision: 1 $ - */ -public class ApplicationsByIdResource extends ApplicationsResource { - public ApplicationsByIdResource(RealmModel realm, RealmAuth auth) { - super(realm, auth); - } - - @Override - protected ApplicationModel getApplicationByPathParam(String id) { - return realm.getApplicationById(id); - } - - @Override - protected String getApplicationPath(ApplicationModel applicationModel) { - return applicationModel.getId(); - } - -} diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ApplicationsResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ApplicationsResource.java deleted file mode 100755 index 13e70616d5..0000000000 --- a/services/src/main/java/org/keycloak/services/resources/admin/ApplicationsResource.java +++ /dev/null @@ -1,124 +0,0 @@ -package org.keycloak.services.resources.admin; - -import org.jboss.logging.Logger; -import org.jboss.resteasy.annotations.cache.NoCache; -import org.jboss.resteasy.spi.NotFoundException; -import org.jboss.resteasy.spi.ResteasyProviderFactory; -import org.keycloak.models.ApplicationModel; -import org.keycloak.models.KeycloakSession; -import org.keycloak.models.ModelDuplicateException; -import org.keycloak.models.RealmModel; -import org.keycloak.models.utils.ModelToRepresentation; -import org.keycloak.models.utils.RepresentationToModel; -import org.keycloak.representations.idm.ApplicationRepresentation; -import org.keycloak.services.resources.flows.Flows; - -import javax.ws.rs.Consumes; -import javax.ws.rs.GET; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.core.Context; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.UriInfo; -import java.util.ArrayList; -import java.util.List; - -/** - * Base resource class for managing a realm's applications. - * - * @author Bill Burke - * @version $Revision: 1 $ - */ -public class ApplicationsResource { - protected static final Logger logger = Logger.getLogger(RealmAdminResource.class); - protected RealmModel realm; - private RealmAuth auth; - - @Context - protected KeycloakSession session; - - public ApplicationsResource(RealmModel realm, RealmAuth auth) { - this.realm = realm; - this.auth = auth; - - auth.init(RealmAuth.Resource.APPLICATION); - } - - /** - * List of applications belonging to this realm. - * - * @return - */ - @GET - @Produces(MediaType.APPLICATION_JSON) - @NoCache - public List getApplications() { - auth.requireAny(); - - List rep = new ArrayList(); - List applicationModels = realm.getApplications(); - - boolean view = auth.hasView(); - for (ApplicationModel applicationModel : applicationModels) { - if (view) { - rep.add(ModelToRepresentation.toRepresentation(applicationModel)); - } else { - ApplicationRepresentation app = new ApplicationRepresentation(); - app.setName(applicationModel.getName()); - rep.add(app); - } - } - - return rep; - } - - /** - * Create a new application. Application name must be unique! - * - * @param uriInfo - * @param rep - * @return - */ - @POST - @Consumes(MediaType.APPLICATION_JSON) - public Response createApplication(final @Context UriInfo uriInfo, final ApplicationRepresentation rep) { - auth.requireManage(); - - try { - ApplicationModel applicationModel = RepresentationToModel.createApplication(session, realm, rep, true); - return Response.created(uriInfo.getAbsolutePathBuilder().path(getApplicationPath(applicationModel)).build()).build(); - } catch (ModelDuplicateException e) { - return Flows.errors().exists("Application " + rep.getName() + " already exists"); - } - } - - protected String getApplicationPath(ApplicationModel applicationModel) { - return applicationModel.getName(); - } - - /** - * Base path for managing a specific application. - * - * @param name - * @return - */ - @Path("{app-name}") - public ApplicationResource getApplication(final @PathParam("app-name") String name) { - ApplicationModel applicationModel = getApplicationByPathParam(name); - if (applicationModel == null) { - throw new NotFoundException("Could not find application: " + name); - } - ApplicationResource applicationResource = new ApplicationResource(realm, auth, applicationModel, session); - ResteasyProviderFactory.getInstance().injectProperties(applicationResource); - //resourceContext.initResource(applicationResource); - return applicationResource; - } - - protected ApplicationModel getApplicationByPathParam(String name) { - return realm.getApplicationByName(name); - } - -} diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ClientAttributeCertificateResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ClientAttributeCertificateResource.java index 1140627af5..b1ec4d167d 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/ClientAttributeCertificateResource.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/ClientAttributeCertificateResource.java @@ -6,8 +6,6 @@ import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataInput; import org.jboss.resteasy.spi.BadRequestException; import org.jboss.resteasy.spi.NotAcceptableException; import org.jboss.resteasy.spi.NotFoundException; -import org.keycloak.events.EventBuilder; -import org.keycloak.events.EventType; import org.keycloak.models.ClientModel; import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ApplicationResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ClientResource.java similarity index 65% rename from services/src/main/java/org/keycloak/services/resources/admin/ApplicationResource.java rename to services/src/main/java/org/keycloak/services/resources/admin/ClientResource.java index 0ee416c991..f0decf37fe 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/ApplicationResource.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/ClientResource.java @@ -5,7 +5,7 @@ import org.jboss.resteasy.annotations.cache.NoCache; import org.jboss.resteasy.spi.BadRequestException; import org.jboss.resteasy.spi.NotFoundException; import org.jboss.resteasy.spi.ResteasyProviderFactory; -import org.keycloak.models.ApplicationModel; +import org.keycloak.models.ClientModel; import org.keycloak.models.KeycloakSession; import org.keycloak.models.ModelDuplicateException; import org.keycloak.models.RealmModel; @@ -16,10 +16,10 @@ import org.keycloak.models.utils.KeycloakModelUtils; import org.keycloak.models.utils.ModelToRepresentation; import org.keycloak.models.utils.RepresentationToModel; import org.keycloak.representations.adapters.action.GlobalRequestResult; -import org.keycloak.representations.idm.ApplicationRepresentation; +import org.keycloak.representations.idm.ClientRepresentation; import org.keycloak.representations.idm.CredentialRepresentation; import org.keycloak.representations.idm.UserSessionRepresentation; -import org.keycloak.services.managers.ApplicationManager; +import org.keycloak.services.managers.ClientManager; import org.keycloak.services.managers.RealmManager; import org.keycloak.services.managers.ResourceAdminManager; import org.keycloak.services.resources.KeycloakApplication; @@ -48,16 +48,16 @@ import java.util.Map; import java.util.Set; /** - * Base resource class for managing one particular application of a realm. + * Base resource class for managing one particular client of a realm. * * @author Bill Burke * @version $Revision: 1 $ */ -public class ApplicationResource { - protected static final Logger logger = Logger.getLogger(ApplicationResource.class); +public class ClientResource { + protected static final Logger logger = Logger.getLogger(ClientResource.class); protected RealmModel realm; private RealmAuth auth; - protected ApplicationModel application; + protected ClientModel client; protected KeycloakSession session; @Context @@ -70,53 +70,53 @@ public class ApplicationResource { return keycloak; } - public ApplicationResource(RealmModel realm, RealmAuth auth, ApplicationModel applicationModel, KeycloakSession session) { + public ClientResource(RealmModel realm, RealmAuth auth, ClientModel clientModel, KeycloakSession session) { this.realm = realm; this.auth = auth; - this.application = applicationModel; + this.client = clientModel; this.session = session; - auth.init(RealmAuth.Resource.APPLICATION); + auth.init(RealmAuth.Resource.CLIENT); } @Path("protocol-mappers") public ProtocolMappersResource getProtocolMappers() { - ProtocolMappersResource mappers = new ProtocolMappersResource(application, auth); + ProtocolMappersResource mappers = new ProtocolMappersResource(client, auth); ResteasyProviderFactory.getInstance().injectProperties(mappers); return mappers; } /** - * Update the application. + * Update the client. * @param rep * @return */ @PUT @Consumes(MediaType.APPLICATION_JSON) - public Response update(final ApplicationRepresentation rep) { + public Response update(final ClientRepresentation rep) { auth.requireManage(); try { - RepresentationToModel.updateApplication(rep, application); + RepresentationToModel.updateClient(rep, client); return Response.noContent().build(); } catch (ModelDuplicateException e) { - return Flows.errors().exists("Application " + rep.getName() + " already exists"); + return Flows.errors().exists("Client " + rep.getClientId() + " already exists"); } } /** - * Get representation of the application. + * Get representation of the client. * * @return */ @GET @NoCache @Produces(MediaType.APPLICATION_JSON) - public ApplicationRepresentation getApplication() { + public ClientRepresentation getClient() { auth.requireView(); - return ModelToRepresentation.toRepresentation(application); + return ModelToRepresentation.toRepresentation(client); } /** @@ -126,12 +126,12 @@ public class ApplicationResource { */ @Path("certificates/{attr}") public ClientAttributeCertificateResource getCertficateResource(@PathParam("attr") String attributePrefix) { - return new ClientAttributeCertificateResource(realm, auth, application, session, attributePrefix); + return new ClientAttributeCertificateResource(realm, auth, client, session, attributePrefix); } /** - * Return keycloak.json file for this application to be used to configure the adapter of that application. + * Return keycloak.json file for this client to be used to configure the adapter of that client. * * @return * @throws IOException @@ -143,15 +143,15 @@ public class ApplicationResource { public String getInstallation() throws IOException { auth.requireView(); - ApplicationManager applicationManager = new ApplicationManager(new RealmManager(session)); - Object rep = applicationManager.toInstallationRepresentation(realm, application, getKeycloakApplication().getBaseUri(uriInfo)); + ClientManager clientManager = new ClientManager(new RealmManager(session)); + Object rep = clientManager.toInstallationRepresentation(realm, client, getKeycloakApplication().getBaseUri(uriInfo)); // TODO Temporary solution to pretty-print return JsonSerialization.mapper.writerWithDefaultPrettyPrinter().writeValueAsString(rep); } /** - * Return XML that can be included in the JBoss/Wildfly Keycloak subsystem to configure the adapter of that application. + * Return XML that can be included in the JBoss/Wildfly Keycloak subsystem to configure the adapter of that client. * * @return * @throws IOException @@ -163,137 +163,137 @@ public class ApplicationResource { public String getJBossInstallation() throws IOException { auth.requireView(); - ApplicationManager applicationManager = new ApplicationManager(new RealmManager(session)); - return applicationManager.toJBossSubsystemConfig(realm, application, getKeycloakApplication().getBaseUri(uriInfo)); + ClientManager clientManager = new ClientManager(new RealmManager(session)); + return clientManager.toJBossSubsystemConfig(realm, client, getKeycloakApplication().getBaseUri(uriInfo)); } /** - * Delete this application. + * Delete this client. * */ @DELETE @NoCache - public void deleteApplication() { + public void deleteClient() { auth.requireManage(); - new ApplicationManager(new RealmManager(session)).removeApplication(realm, application); + new ClientManager(new RealmManager(session)).removeClient(realm, client); } /** - * Generates a new secret for this application + * Generates a new secret for this client * * @return */ @Path("client-secret") @POST - @Produces("application/json") - @Consumes("application/json") + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) public CredentialRepresentation regenerateSecret() { auth.requireManage(); logger.debug("regenerateSecret"); - UserCredentialModel cred = KeycloakModelUtils.generateSecret(application); + UserCredentialModel cred = KeycloakModelUtils.generateSecret(client); CredentialRepresentation rep = ModelToRepresentation.toRepresentation(cred); return rep; } /** - * Get the secret of this application + * Get the secret of this client * * @return */ @Path("client-secret") @GET @NoCache - @Produces("application/json") + @Produces(MediaType.APPLICATION_JSON) public CredentialRepresentation getClientSecret() { auth.requireView(); logger.debug("getClientSecret"); - UserCredentialModel model = UserCredentialModel.secret(application.getSecret()); - if (model == null) throw new NotFoundException("Application does not have a secret"); + UserCredentialModel model = UserCredentialModel.secret(client.getSecret()); + if (model == null) throw new NotFoundException("Client does not have a secret"); return ModelToRepresentation.toRepresentation(model); } /** - * Base path for managing the scope mappings for this application + * Base path for managing the scope mappings for this client * * @return */ @Path("scope-mappings") public ScopeMappedResource getScopeMappedResource() { - return new ScopeMappedResource(realm, auth, application, session); + return new ScopeMappedResource(realm, auth, client, session); } @Path("roles") public RoleContainerResource getRoleContainerResource() { - return new RoleContainerResource(realm, auth, application); + return new RoleContainerResource(realm, auth, client); } /** * Returns set of allowed origin. This is used for CORS requests. Access tokens will have - * their allowedOrigins claim set to this value for tokens created for this application. + * their allowedOrigins claim set to this value for tokens created for this client. * * @return */ @Path("allowed-origins") @GET @NoCache - @Produces("application/json") + @Produces(MediaType.APPLICATION_JSON) public Set getAllowedOrigins() { auth.requireView(); - return application.getWebOrigins(); + return client.getWebOrigins(); } /** * Change the set of allowed origins. This is used for CORS requests. Access tokens will have - * their allowedOrigins claim set to this value for tokens created for this application. + * their allowedOrigins claim set to this value for tokens created for this client. * * @param allowedOrigins */ @Path("allowed-origins") @PUT - @Consumes("application/json") + @Consumes(MediaType.APPLICATION_JSON) public void updateAllowedOrigins(Set allowedOrigins) { auth.requireManage(); - application.setWebOrigins(allowedOrigins); + client.setWebOrigins(allowedOrigins); } /** * Remove set of allowed origins from current allowed origins list. This is used for CORS requests. Access tokens will have - * their allowedOrigins claim set to this value for tokens created for this application. + * their allowedOrigins claim set to this value for tokens created for this client. * * @param allowedOrigins */ @Path("allowed-origins") @DELETE - @Consumes("application/json") + @Consumes(MediaType.APPLICATION_JSON) public void deleteAllowedOrigins(Set allowedOrigins) { auth.requireManage(); for (String origin : allowedOrigins) { - application.removeWebOrigin(origin); + client.removeWebOrigin(origin); } } /** - * If the application has an admin URL, push the application's revocation policy to it. + * If the client has an admin URL, push the client's revocation policy to it. * */ @Path("push-revocation") @POST public GlobalRequestResult pushRevocation() { auth.requireManage(); - return new ResourceAdminManager().pushApplicationRevocationPolicy(uriInfo.getRequestUri(), realm, application); + return new ResourceAdminManager().pushClientRevocationPolicy(uriInfo.getRequestUri(), realm, client); } /** - * Number of user sessions associated with this application + * Number of user sessions associated with this client * * { * "count": number @@ -308,12 +308,12 @@ public class ApplicationResource { public Map getApplicationSessionCount() { auth.requireView(); Map map = new HashMap(); - map.put("count", session.sessions().getActiveUserSessions(application.getRealm(), application)); + map.put("count", session.sessions().getActiveUserSessions(client.getRealm(), client)); return map; } /** - * Return a list of user sessions associated with this application + * Return a list of user sessions associated with this client * * @return */ @@ -326,7 +326,7 @@ public class ApplicationResource { firstResult = firstResult != null ? firstResult : -1; maxResults = maxResults != null ? maxResults : -1; List sessions = new ArrayList(); - for (UserSessionModel userSession : session.sessions().getUserSessions(application.getRealm(), application, firstResult, maxResults)) { + for (UserSessionModel userSession : session.sessions().getUserSessions(client.getRealm(), client, firstResult, maxResults)) { UserSessionRepresentation rep = ModelToRepresentation.toRepresentation(userSession); sessions.add(rep); } @@ -334,18 +334,18 @@ public class ApplicationResource { } /** - * If the application has an admin URL, invalidate all sessions associated with that application directly. + * If the client has an admin URL, invalidate all sessions associated with that client directly. * */ @Path("logout-all") @POST public GlobalRequestResult logoutAll() { auth.requireManage(); - return new ResourceAdminManager().logoutApplication(uriInfo.getRequestUri(), realm, application); + return new ResourceAdminManager().logoutClient(uriInfo.getRequestUri(), realm, client); } /** - * If the application has an admin URL, invalidate the sessions for a particular user directly. + * If the client has an admin URL, invalidate the sessions for a particular user directly. * */ @Path("logout-user/{username}") @@ -356,18 +356,18 @@ public class ApplicationResource { if (user == null) { throw new NotFoundException("User not found"); } - new ResourceAdminManager().logoutUserFromApplication(uriInfo.getRequestUri(), realm, application, user, session); + new ResourceAdminManager().logoutUserFromClient(uriInfo.getRequestUri(), realm, client, user, session); } /** - * Manually register cluster node to this application - usually it's not needed to call this directly as adapter should handle + * Manually register cluster node to this client - usually it's not needed to call this directly as adapter should handle * by sending registration request to Keycloak * * @param formParams */ @Path("nodes") @POST - @Consumes("application/json") + @Consumes(MediaType.APPLICATION_JSON) public void registerNode(Map formParams) { auth.requireManage(); String node = formParams.get("node"); @@ -375,11 +375,11 @@ public class ApplicationResource { throw new BadRequestException("Node not found in params"); } if (logger.isDebugEnabled()) logger.debug("Register node: " + node); - application.registerNode(node, Time.currentTime()); + client.registerNode(node, Time.currentTime()); } /** - * Unregister cluster node from this application + * Unregister cluster node from this client * * @param node */ @@ -390,12 +390,12 @@ public class ApplicationResource { auth.requireManage(); if (logger.isDebugEnabled()) logger.debug("Unregister node: " + node); - Integer time = application.getRegisteredNodes().get(node); + Integer time = client.getRegisteredNodes().get(node); if (time == null) { - throw new NotFoundException("Application does not have a node " + node); + throw new NotFoundException("Client does not have a node " + node); } - application.unregisterNode(node); + client.unregisterNode(node); } /** @@ -410,7 +410,7 @@ public class ApplicationResource { auth.requireManage(); logger.debug("Test availability of cluster nodes"); - return new ResourceAdminManager().testNodesAvailability(uriInfo.getRequestUri(), realm, application); + return new ResourceAdminManager().testNodesAvailability(uriInfo.getRequestUri(), realm, client); } } diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ClientsByIdResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ClientsByIdResource.java new file mode 100755 index 0000000000..46f2f8774d --- /dev/null +++ b/services/src/main/java/org/keycloak/services/resources/admin/ClientsByIdResource.java @@ -0,0 +1,25 @@ +package org.keycloak.services.resources.admin; + +import org.keycloak.models.ClientModel; +import org.keycloak.models.RealmModel; + +/** + * @author Bill Burke + * @version $Revision: 1 $ + */ +public class ClientsByIdResource extends ClientsResource { + public ClientsByIdResource(RealmModel realm, RealmAuth auth) { + super(realm, auth); + } + + @Override + protected ClientModel getClientByPathParam(String id) { + return realm.getClientById(id); + } + + @Override + protected String getClientPath(ClientModel clientModel) { + return clientModel.getId(); + } + +} diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ClientsResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ClientsResource.java new file mode 100755 index 0000000000..270b7ac4e4 --- /dev/null +++ b/services/src/main/java/org/keycloak/services/resources/admin/ClientsResource.java @@ -0,0 +1,123 @@ +package org.keycloak.services.resources.admin; + +import org.jboss.logging.Logger; +import org.jboss.resteasy.annotations.cache.NoCache; +import org.jboss.resteasy.spi.NotFoundException; +import org.jboss.resteasy.spi.ResteasyProviderFactory; +import org.keycloak.models.ClientModel; +import org.keycloak.models.KeycloakSession; +import org.keycloak.models.ModelDuplicateException; +import org.keycloak.models.RealmModel; +import org.keycloak.models.utils.ModelToRepresentation; +import org.keycloak.models.utils.RepresentationToModel; +import org.keycloak.representations.idm.ClientRepresentation; +import org.keycloak.services.resources.flows.Flows; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; +import java.util.ArrayList; +import java.util.List; + +/** + * Base resource class for managing a realm's clients. + * + * @author Bill Burke + * @version $Revision: 1 $ + */ +public class ClientsResource { + protected static final Logger logger = Logger.getLogger(RealmAdminResource.class); + protected RealmModel realm; + private RealmAuth auth; + + @Context + protected KeycloakSession session; + + public ClientsResource(RealmModel realm, RealmAuth auth) { + this.realm = realm; + this.auth = auth; + + auth.init(RealmAuth.Resource.CLIENT); + } + + /** + * List of clients belonging to this realm. + * + * @return + */ + @GET + @Produces(MediaType.APPLICATION_JSON) + @NoCache + public List getClients() { + auth.requireAny(); + + List rep = new ArrayList<>(); + List clientModels = realm.getClients(); + + boolean view = auth.hasView(); + for (ClientModel clientModel : clientModels) { + if (view) { + rep.add(ModelToRepresentation.toRepresentation(clientModel)); + } else { + ClientRepresentation client = new ClientRepresentation(); + client.setClientId(clientModel.getClientId()); + rep.add(client); + } + } + + return rep; + } + + /** + * Create a new client. Client client_id must be unique! + * + * @param uriInfo + * @param rep + * @return + */ + @POST + @Consumes(MediaType.APPLICATION_JSON) + public Response createClient(final @Context UriInfo uriInfo, final ClientRepresentation rep) { + auth.requireManage(); + + try { + ClientModel clientModel = RepresentationToModel.createClient(session, realm, rep, true); + return Response.created(uriInfo.getAbsolutePathBuilder().path(getClientPath(clientModel)).build()).build(); + } catch (ModelDuplicateException e) { + return Flows.errors().exists("Client " + rep.getClientId() + " already exists"); + } + } + + protected String getClientPath(ClientModel clientModel) { + return clientModel.getClientId(); + } + + /** + * Base path for managing a specific client. + * + * @param name + * @return + */ + @Path("{app-name}") + public ClientResource getClient(final @PathParam("app-name") String name) { + ClientModel clientModel = getClientByPathParam(name); + if (clientModel == null) { + throw new NotFoundException("Could not find client: " + name); + } + ClientResource clientResource = new ClientResource(realm, auth, clientModel, session); + ResteasyProviderFactory.getInstance().injectProperties(clientResource); + return clientResource; + } + + protected ClientModel getClientByPathParam(String name) { + return realm.getClientByClientId(name); + } + +} diff --git a/services/src/main/java/org/keycloak/services/resources/admin/IdentityProviderResource.java b/services/src/main/java/org/keycloak/services/resources/admin/IdentityProviderResource.java index 07444afbdc..bbb32b441b 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/IdentityProviderResource.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/IdentityProviderResource.java @@ -4,8 +4,8 @@ import org.jboss.logging.Logger; import org.jboss.resteasy.annotations.cache.NoCache; import org.keycloak.broker.provider.IdentityProvider; import org.keycloak.broker.provider.IdentityProviderFactory; -import org.keycloak.models.ClientIdentityProviderMappingModel; import org.keycloak.models.ClientModel; +import org.keycloak.models.ClientIdentityProviderMappingModel; import org.keycloak.models.FederatedIdentityModel; import org.keycloak.models.IdentityProviderModel; import org.keycloak.models.KeycloakSession; @@ -27,6 +27,7 @@ import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; import java.util.ArrayList; @@ -53,7 +54,7 @@ public class IdentityProviderResource { @GET @NoCache - @Produces("application/json") + @Produces(MediaType.APPLICATION_JSON) public IdentityProviderRepresentation getIdentityProvider() { IdentityProviderRepresentation rep = ModelToRepresentation.toRepresentation(this.identityProviderModel); @@ -65,8 +66,7 @@ public class IdentityProviderResource { public Response delete() { this.auth.requireManage(); - removeClientIdentityProviders(this.realm.getApplications(), this.identityProviderModel); - removeClientIdentityProviders(this.realm.getOAuthClients(), this.identityProviderModel); + removeClientIdentityProviders(this.realm.getClients(), this.identityProviderModel); this.realm.removeIdentityProviderByAlias(this.identityProviderModel.getAlias()); @@ -74,7 +74,7 @@ public class IdentityProviderResource { } @PUT - @Consumes("application/json") + @Consumes(MediaType.APPLICATION_JSON) public Response update(IdentityProviderRepresentation providerRep) { try { this.auth.requireManage(); @@ -90,8 +90,7 @@ public class IdentityProviderResource { // Admin changed the ID (alias) of identity provider. We must update all clients and users logger.debug("Changing providerId in all clients and linked users. oldProviderId=" + oldProviderId + ", newProviderId=" + newProviderId); - updateClientsAfterProviderAliasChange(this.realm.getApplications(), oldProviderId, newProviderId); - updateClientsAfterProviderAliasChange(this.realm.getOAuthClients(), oldProviderId, newProviderId); + updateClientsAfterProviderAliasChange(this.realm.getClients(), oldProviderId, newProviderId); updateUsersAfterProviderAliasChange(this.session.users().getUsers(this.realm), oldProviderId, newProviderId); } @@ -113,7 +112,7 @@ public class IdentityProviderResource { return null; } - private void updateClientsAfterProviderAliasChange(List clients, String oldProviderId, String newProviderId) { + private void updateClientsAfterProviderAliasChange(List clients, String oldProviderId, String newProviderId) { for (ClientModel client : clients) { List clientIdentityProviders = client.getIdentityProviders(); boolean found = true; @@ -175,11 +174,11 @@ public class IdentityProviderResource { } - private void removeClientIdentityProviders(List clients, IdentityProviderModel identityProvider) { + private void removeClientIdentityProviders(List clients, IdentityProviderModel identityProvider) { for (ClientModel clientModel : clients) { List identityProviders = clientModel.getIdentityProviders(); - for (ClientIdentityProviderMappingModel providerMappingModel : new ArrayList(identityProviders)) { + for (ClientIdentityProviderMappingModel providerMappingModel : new ArrayList<>(identityProviders)) { if (providerMappingModel.getIdentityProvider().equals(identityProvider.getAlias())) { identityProviders.remove(providerMappingModel); clientModel.updateIdentityProviders(identityProviders); diff --git a/services/src/main/java/org/keycloak/services/resources/admin/IdentityProvidersResource.java b/services/src/main/java/org/keycloak/services/resources/admin/IdentityProvidersResource.java index e59ee6e52e..ef0e94bd25 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/IdentityProvidersResource.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/IdentityProvidersResource.java @@ -57,7 +57,7 @@ public class IdentityProvidersResource { @Path("/providers/{provider_id}") @GET @NoCache - @Produces("application/json") + @Produces(MediaType.APPLICATION_JSON) public Response getIdentityProviders(@PathParam("provider_id") String providerId) { this.auth.requireView(); IdentityProviderFactory providerFactory = getProviderFactorytById(providerId); @@ -108,7 +108,7 @@ public class IdentityProvidersResource { @GET @Path("instances") @NoCache - @Produces("application/json") + @Produces(MediaType.APPLICATION_JSON) public List getIdentityProviders() { this.auth.requireView(); diff --git a/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientResource.java b/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientResource.java deleted file mode 100755 index b69fb83c29..0000000000 --- a/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientResource.java +++ /dev/null @@ -1,206 +0,0 @@ -package org.keycloak.services.resources.admin; - -import org.jboss.logging.Logger; -import org.jboss.resteasy.annotations.cache.NoCache; -import org.jboss.resteasy.spi.NotFoundException; -import org.jboss.resteasy.spi.ResteasyProviderFactory; -import org.keycloak.models.KeycloakSession; -import org.keycloak.models.ModelDuplicateException; -import org.keycloak.models.OAuthClientModel; -import org.keycloak.models.RealmModel; -import org.keycloak.models.UserCredentialModel; -import org.keycloak.models.utils.ModelToRepresentation; -import org.keycloak.models.utils.RepresentationToModel; -import org.keycloak.representations.idm.CredentialRepresentation; -import org.keycloak.representations.idm.OAuthClientRepresentation; -import org.keycloak.services.managers.OAuthClientManager; -import org.keycloak.services.managers.RealmManager; -import org.keycloak.services.resources.KeycloakApplication; -import org.keycloak.services.resources.flows.Flows; -import org.keycloak.util.JsonSerialization; - -import javax.ws.rs.Consumes; -import javax.ws.rs.DELETE; -import javax.ws.rs.GET; -import javax.ws.rs.POST; -import javax.ws.rs.PUT; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.core.Context; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.UriInfo; -import java.io.IOException; - -/** - * Base resource class for managing oauth clients - * - * @author Bill Burke - * @version $Revision: 1 $ - */ -public class OAuthClientResource { - protected static final Logger logger = Logger.getLogger(RealmAdminResource.class); - protected RealmModel realm; - private RealmAuth auth; - protected OAuthClientModel oauthClient; - protected KeycloakSession session; - @Context - protected UriInfo uriInfo; - - @Context - protected KeycloakApplication application; - - protected KeycloakApplication getApplication() { - return (KeycloakApplication)application; - } - - public OAuthClientResource(RealmModel realm, RealmAuth auth, OAuthClientModel oauthClient, KeycloakSession session) { - this.realm = realm; - this.auth = auth; - this.oauthClient = oauthClient; - this.session = session; - - auth.init(RealmAuth.Resource.CLIENT); - } - - /** - * interface for updating attached ProtocolMappers - * - * @return - */ - @Path("protocol-mappers") - public ProtocolMappersResource getProtocolMappers() { - ProtocolMappersResource mappers = new ProtocolMappersResource(oauthClient, auth); - ResteasyProviderFactory.getInstance().injectProperties(mappers); - //resourceContext.initResource(mappers); - return mappers; - } - - /** - * - * @param attributePrefix - * @return - */ - @Path("certificates/{attr}") - public ClientAttributeCertificateResource getCertficateResource(@PathParam("attr") String attributePrefix) { - return new ClientAttributeCertificateResource(realm, auth, oauthClient, session, attributePrefix); - } - - - - /** - * Update the oauth client - * - * @param rep - * @return - */ - @PUT - @Consumes(MediaType.APPLICATION_JSON) - public Response update(final OAuthClientRepresentation rep) { - auth.requireManage(); - - try { - RepresentationToModel.updateOAuthClient(session, rep, oauthClient); - return Response.noContent().build(); - } catch (ModelDuplicateException e) { - return Flows.errors().exists("Client " + rep.getName() + " already exists"); - } - } - - /** - * Get a representation of the oauth client - * - * @return - */ - @GET - @NoCache - @Produces(MediaType.APPLICATION_JSON) - public OAuthClientRepresentation getOAuthClient() { - auth.requireView(); - - return ModelToRepresentation.toRepresentation(oauthClient); - } - - /** - * Get an example keycloak.json file to use to configure the oauth client - * - * @return - * @throws IOException - */ - @GET - @NoCache - @Path("installation") - @Produces(MediaType.APPLICATION_JSON) - public String getInstallation() throws IOException { - auth.requireView(); - - OAuthClientManager manager = new OAuthClientManager(); - Object rep = manager.toInstallationRepresentation(realm, oauthClient, getApplication().getBaseUri(uriInfo)); - - // TODO Temporary solution to pretty-print - return JsonSerialization.mapper.writerWithDefaultPrettyPrinter().writeValueAsString(rep); - } - - /** - * Remove the OAuth Client - * - */ - @DELETE - @NoCache - public void deleteOAuthClient() { - auth.requireManage(); - - new OAuthClientManager(new RealmManager(session)).removeClient(realm, oauthClient); - } - - - /** - * Generate a new client secret for the oauth client - * - * @return - */ - @Path("client-secret") - @POST - @Produces("application/json") - @Consumes("application/json") - public CredentialRepresentation regenerateSecret() { - auth.requireManage(); - - logger.debug("regenerateSecret"); - UserCredentialModel cred = UserCredentialModel.generateSecret(); - oauthClient.setSecret(cred.getValue()); - CredentialRepresentation rep = ModelToRepresentation.toRepresentation(cred); - return rep; - } - - /** - * Get the secret of the oauth client - * - * @return - */ - @Path("client-secret") - @GET - @NoCache - @Produces("application/json") - public CredentialRepresentation getClientSecret() { - auth.requireView(); - - logger.debug("getClientSecret"); - UserCredentialModel model = UserCredentialModel.secret(oauthClient.getSecret()); - if (model == null) throw new NotFoundException("Application does not have a secret"); - return ModelToRepresentation.toRepresentation(model); - } - - /** - * Base path for managing the oauth client's scope - * - * @return - */ - @Path("scope-mappings") - public ScopeMappedResource getScopeMappedResource() { - return new ScopeMappedResource(realm, auth, oauthClient, session); - } - - -} diff --git a/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientsByIdResource.java b/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientsByIdResource.java deleted file mode 100755 index 91a19db8fc..0000000000 --- a/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientsByIdResource.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.keycloak.services.resources.admin; - -import org.keycloak.models.KeycloakSession; -import org.keycloak.models.OAuthClientModel; -import org.keycloak.models.RealmModel; - -/** - * @author Bill Burke - * @version $Revision: 1 $ - */ -public class OAuthClientsByIdResource extends OAuthClientsResource { - public OAuthClientsByIdResource(RealmModel realm, RealmAuth auth, KeycloakSession session) { - super(realm, auth, session); - } - - @Override - protected OAuthClientModel getOAuthClientModel(String id) { - return realm.getOAuthClientById(id); - } - - @Override - protected String getClientPath(OAuthClientModel oauth) { - return oauth.getId(); - } - -} diff --git a/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientsResource.java b/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientsResource.java deleted file mode 100755 index cac3d8af8d..0000000000 --- a/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientsResource.java +++ /dev/null @@ -1,121 +0,0 @@ -package org.keycloak.services.resources.admin; - -import org.jboss.logging.Logger; -import org.jboss.resteasy.annotations.cache.NoCache; -import org.jboss.resteasy.spi.NotFoundException; -import org.jboss.resteasy.spi.ResteasyProviderFactory; -import org.keycloak.models.KeycloakSession; -import org.keycloak.models.ModelDuplicateException; -import org.keycloak.models.OAuthClientModel; -import org.keycloak.models.RealmModel; -import org.keycloak.models.utils.ModelToRepresentation; -import org.keycloak.models.utils.RepresentationToModel; -import org.keycloak.representations.idm.OAuthClientRepresentation; -import org.keycloak.services.resources.flows.Flows; - -import javax.ws.rs.Consumes; -import javax.ws.rs.GET; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.core.Context; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.UriInfo; -import java.util.ArrayList; -import java.util.List; - -/** - * @author Bill Burke - * @version $Revision: 1 $ - */ -public class OAuthClientsResource { - protected static final Logger logger = Logger.getLogger(RealmAdminResource.class); - protected RealmModel realm; - protected KeycloakSession session; - private RealmAuth auth; - - public OAuthClientsResource(RealmModel realm, RealmAuth auth, KeycloakSession session) { - this.auth = auth; - this.realm = realm; - this.session = session; - - auth.init(RealmAuth.Resource.CLIENT); - } - - /** - * Get a list of oauth clients in this realm. - * - * @return - */ - @GET - @Produces(MediaType.APPLICATION_JSON) - @NoCache - public List getOAuthClients() { - List rep = new ArrayList(); - List oauthModels = realm.getOAuthClients(); - - boolean view = auth.hasView(); - for (OAuthClientModel oauth : oauthModels) { - if (view) { - rep.add(ModelToRepresentation.toRepresentation(oauth)); - } else { - OAuthClientRepresentation client = new OAuthClientRepresentation(); - client.setName(oauth.getClientId()); - rep.add(client); - } - } - - return rep; - } - - /** - * Create an oauth client - * - * @param uriInfo - * @param rep - * @return - */ - @POST - @Consumes(MediaType.APPLICATION_JSON) - public Response createOAuthClient(final @Context UriInfo uriInfo, final OAuthClientRepresentation rep) { - auth.requireManage(); - - try { - OAuthClientModel oauth = RepresentationToModel.createOAuthClient(session, rep, realm); - return Response.created(uriInfo.getAbsolutePathBuilder().path(getClientPath(oauth)).build()).build(); - } catch (ModelDuplicateException e) { - return Flows.errors().exists("Client " + rep.getName() + " already exists"); - } - } - - protected String getClientPath(OAuthClientModel oauth) { - return oauth.getClientId(); - } - - /** - * Base path to manage one specific oauth client - * - * @param clientId oauth client's clientId - * @return - */ - @Path("{clientId}") - public OAuthClientResource getOAuthClient(final @PathParam("clientId") String clientId) { - auth.requireView(); - - OAuthClientModel oauth = getOAuthClientModel(clientId); - if (oauth == null) { - throw new NotFoundException("OAuth Client not found"); - } - OAuthClientResource oAuthClientResource = new OAuthClientResource(realm, auth, oauth, session); - ResteasyProviderFactory.getInstance().injectProperties(oAuthClientResource); - //resourceContext.initResource(oAuthClientResource); - return oAuthClientResource; - } - - protected OAuthClientModel getOAuthClientModel(String clientId) { - return realm.getOAuthClient(clientId); - } - -} diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ProtocolMappersResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ProtocolMappersResource.java index 717a1168a3..36428b89fb 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/ProtocolMappersResource.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/ProtocolMappersResource.java @@ -19,9 +19,9 @@ import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; - import java.util.LinkedList; import java.util.List; @@ -60,7 +60,7 @@ public class ProtocolMappersResource { @GET @NoCache @Path("protocol/{protocol}") - @Produces("application/json") + @Produces(MediaType.APPLICATION_JSON) public List getMappersPerProtocol(@PathParam("protocol") String protocol) { auth.requireView(); List mappers = new LinkedList(); @@ -78,7 +78,7 @@ public class ProtocolMappersResource { @Path("models") @POST @NoCache - @Consumes("application/json") + @Consumes(MediaType.APPLICATION_JSON) public Response createMapper(ProtocolMapperRepresentation rep) { auth.requireManage(); ProtocolMapperModel model = RepresentationToModel.toModel(rep); @@ -92,7 +92,7 @@ public class ProtocolMappersResource { @Path("add-models") @POST @NoCache - @Consumes("application/json") + @Consumes(MediaType.APPLICATION_JSON) public void createMapper(List reps) { auth.requireManage(); for (ProtocolMapperRepresentation rep : reps) { @@ -104,7 +104,7 @@ public class ProtocolMappersResource { @GET @NoCache @Path("models") - @Produces("application/json") + @Produces(MediaType.APPLICATION_JSON) public List getMappers() { auth.requireView(); List mappers = new LinkedList(); @@ -117,7 +117,7 @@ public class ProtocolMappersResource { @GET @NoCache @Path("models/{id}") - @Produces("application/json") + @Produces(MediaType.APPLICATION_JSON) public ProtocolMapperRepresentation getMapperById(@PathParam("id") String id) { auth.requireView(); ProtocolMapperModel model = client.getProtocolMapperById(id); @@ -128,7 +128,7 @@ public class ProtocolMappersResource { @PUT @NoCache @Path("models/{id}") - @Consumes("application/json") + @Consumes(MediaType.APPLICATION_JSON) public void update(@PathParam("id") String id, ProtocolMapperRepresentation rep) { auth.requireManage(); ProtocolMapperModel model = client.getProtocolMapperById(id); @@ -147,6 +147,4 @@ public class ProtocolMappersResource { client.removeProtocolMapper(model); } - - } diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java index 34cd97eaf0..5fea57dfbf 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java @@ -9,8 +9,8 @@ import org.keycloak.events.Event; import org.keycloak.events.EventQuery; import org.keycloak.events.EventStoreProvider; import org.keycloak.events.EventType; -import org.keycloak.exportimport.ApplicationImporter; -import org.keycloak.models.ApplicationModel; +import org.keycloak.exportimport.ClientImporter; +import org.keycloak.models.ClientModel; import org.keycloak.models.KeycloakSession; import org.keycloak.models.ModelDuplicateException; import org.keycloak.models.RealmModel; @@ -46,7 +46,6 @@ import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; - import java.util.HashMap; import java.util.LinkedList; import java.util.List; @@ -86,66 +85,38 @@ public class RealmAdminResource { } /** - * Base path for importing applications under this realm. + * Base path for importing clients under this realm. * * @return */ - @Path("application-importers/{formatId}") - public Object getApplicationImporter(@PathParam("formatId") String formatId) { - ApplicationImporter importer = session.getProvider(ApplicationImporter.class, formatId); + @Path("client-importers/{formatId}") + public Object getClientImporter(@PathParam("formatId") String formatId) { + ClientImporter importer = session.getProvider(ClientImporter.class, formatId); return importer.createJaxrsService(realm, auth); } /** - * Base path for managing applications under this realm. + * Base path for managing clients under this realm. * * @return */ - @Path("applications") - public ApplicationsResource getApplications() { - ApplicationsResource applicationsResource = new ApplicationsResource(realm, auth); - ResteasyProviderFactory.getInstance().injectProperties(applicationsResource); - //resourceContext.initResource(applicationsResource); - return applicationsResource; + @Path("clients") + public ClientsResource getClients() { + ClientsResource clientsResource = new ClientsResource(realm, auth); + ResteasyProviderFactory.getInstance().injectProperties(clientsResource); + return clientsResource; } /** - * Base path for managing applications under this realm. + * Base path for managing clients under this realm. * * @return */ - @Path("applications-by-id") - public ApplicationsByIdResource getApplicationsById() { - ApplicationsByIdResource applicationsResource = new ApplicationsByIdResource(realm, auth); - ResteasyProviderFactory.getInstance().injectProperties(applicationsResource); - //resourceContext.initResource(applicationsResource); - return applicationsResource; - } - - /** - * base path for managing oauth clients in this realm uses name of client - * - * @return - */ - @Path("oauth-clients") - public OAuthClientsResource getOAuthClients() { - OAuthClientsResource oauth = new OAuthClientsResource(realm, auth, session); - ResteasyProviderFactory.getInstance().injectProperties(oauth); - //resourceContext.initResource(oauth); - return oauth; - } - - /** - * base path for managing oauth clients in this realm uses ids - * - * @return - */ - @Path("oauth-clients-by-id") - public OAuthClientsByIdResource getOAuthClientsById() { - OAuthClientsByIdResource oauth = new OAuthClientsByIdResource(realm, auth, session); - ResteasyProviderFactory.getInstance().injectProperties(oauth); - //resourceContext.initResource(oauth); - return oauth; + @Path("clients-by-id") + public ClientsByIdResource getClientsById() { + ClientsByIdResource clientsResource = new ClientsByIdResource(realm, auth); + ResteasyProviderFactory.getInstance().injectProperties(clientsResource); + return clientsResource; } /** @@ -159,14 +130,13 @@ public class RealmAdminResource { } /** - * Get the top-level representation of the realm. It will not include nested information like User, Application, or OAuth - * Client representations. + * Get the top-level representation of the realm. It will not include nested information like User and Client representations. * * @return */ @GET @NoCache - @Produces("application/json") + @Produces(MediaType.APPLICATION_JSON) public RealmRepresentation getRealm() { if (auth.hasView()) { RealmRepresentation rep = ModelToRepresentation.toRepresentation(realm, false); @@ -189,14 +159,14 @@ public class RealmAdminResource { } /** - * Update the top-level information of this realm. Any user, roles, application, or oauth client information in the representation + * Update the top-level information of this realm. Any user, roles or client information in the representation * will be ignored. This will only update top-level attributes of the realm. * * @param rep * @return */ @PUT - @Consumes("application/json") + @Consumes(MediaType.APPLICATION_JSON) public Response updateRealm(final RealmRepresentation rep) { auth.requireManage(); @@ -264,7 +234,7 @@ public class RealmAdminResource { } /** - * Path for managing all realm-level or application-level roles defined in this realm by it's id. + * Path for managing all realm-level or client-level roles defined in this realm by it's id. * * @return */ @@ -277,7 +247,7 @@ public class RealmAdminResource { } /** - * Push the realm's revocation policy to any application that has an admin url associated with it. + * Push the realm's revocation policy to any client that has an admin url associated with it. * */ @Path("push-revocation") @@ -288,7 +258,7 @@ public class RealmAdminResource { } /** - * Removes all user sessions. Any application that has an admin url will also be told to invalidate any sessions + * Removes all user sessions. Any client that has an admin url will also be told to invalidate any sessions * they have. * */ @@ -300,7 +270,7 @@ public class RealmAdminResource { } /** - * Remove a specific user session. Any application that has an admin url will also be told to invalidate this + * Remove a specific user session. Any client that has an admin url will also be told to invalidate this * particular session. * * @param sessionId @@ -314,46 +284,46 @@ public class RealmAdminResource { } /** - * Returns a JSON map. The key is the application name, the value is the number of sessions that currently are active - * with that application. Only application's that actually have a session associated with them will be in this map. + * Returns a JSON map. The key is the client name, the value is the number of sessions that currently are active + * with that client. Only client's that actually have a session associated with them will be in this map. * * @return */ - @Path("application-session-stats") + @Path("client-session-stats") @GET @NoCache @Produces(MediaType.APPLICATION_JSON) @Deprecated - public Map getApplicationSessionStats() { + public Map getClientSessionStats() { auth.requireView(); Map stats = new HashMap(); - for (ApplicationModel application : realm.getApplications()) { - int size = session.sessions().getActiveUserSessions(application.getRealm(), application); + for (ClientModel client : realm.getClients()) { + int size = session.sessions().getActiveUserSessions(client.getRealm(), client); if (size == 0) continue; - stats.put(application.getName(), size); + stats.put(client.getClientId(), size); } return stats; } /** - * Returns a JSON map. The key is the application id, the value is the number of sessions that currently are active - * with that application. Only application's that actually have a session associated with them will be in this map. + * Returns a JSON map. The key is the client id, the value is the number of sessions that currently are active + * with that client. Only client's that actually have a session associated with them will be in this map. * * @return */ - @Path("application-by-id-session-stats") + @Path("client-by-id-session-stats") @GET @NoCache @Produces(MediaType.APPLICATION_JSON) - public List> getApplicationByIdSessionStats() { + public List> getClientByIdSessionStats() { auth.requireView(); List> data = new LinkedList>(); - for (ApplicationModel application : realm.getApplications()) { - int size = session.sessions().getActiveUserSessions(application.getRealm(), application); + for (ClientModel client : realm.getClients()) { + int size = session.sessions().getActiveUserSessions(client.getRealm(), client); if (size == 0) continue; Map map = new HashMap(); - map.put("id", application.getId()); - map.put("name", application.getName()); + map.put("id", client.getId()); + map.put("clientId", client.getClientId()); map.put("active", size + ""); data.add(map); } @@ -368,7 +338,7 @@ public class RealmAdminResource { @GET @NoCache @Path("events/config") - @Produces("application/json") + @Produces(MediaType.APPLICATION_JSON) public RealmEventsConfigRepresentation getRealmEventsConfig() { auth.init(RealmAuth.Resource.EVENTS).requireView(); @@ -382,7 +352,7 @@ public class RealmAdminResource { */ @PUT @Path("events/config") - @Consumes("application/json") + @Consumes(MediaType.APPLICATION_JSON) public void updateRealmEventsConfig(final RealmEventsConfigRepresentation rep) { auth.init(RealmAuth.Resource.EVENTS).requireManage(); diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RealmAuth.java b/services/src/main/java/org/keycloak/services/resources/admin/RealmAuth.java index 20238f1b00..f93e8c7b43 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/RealmAuth.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/RealmAuth.java @@ -1,7 +1,7 @@ package org.keycloak.services.resources.admin; import org.keycloak.models.AdminRoles; -import org.keycloak.models.ApplicationModel; +import org.keycloak.models.ClientModel; import org.keycloak.services.ForbiddenException; @@ -13,13 +13,13 @@ public class RealmAuth { private Resource resource; public enum Resource { - APPLICATION, CLIENT, USER, REALM, EVENTS, IDENTITY_PROVIDER + CLIENT, USER, REALM, EVENTS, IDENTITY_PROVIDER } private AdminAuth auth; - private ApplicationModel realmAdminApp; + private ClientModel realmAdminApp; - public RealmAuth(AdminAuth auth, ApplicationModel realmAdminApp) { + public RealmAuth(AdminAuth auth, ClientModel realmAdminApp) { this.auth = auth; this.realmAdminApp = realmAdminApp; } @@ -57,8 +57,6 @@ public class RealmAuth { private String getViewRole(Resource resource) { switch (resource) { - case APPLICATION: - return AdminRoles.VIEW_APPLICATIONS; case CLIENT: return AdminRoles.VIEW_CLIENTS; case USER: @@ -76,8 +74,6 @@ public class RealmAuth { private String getManageRole(Resource resource) { switch (resource) { - case APPLICATION: - return AdminRoles.MANAGE_APPLICATIONS; case CLIENT: return AdminRoles.MANAGE_CLIENTS; case USER: diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RealmsAdminResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RealmsAdminResource.java index 07b29b2248..21fc79e952 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/RealmsAdminResource.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/RealmsAdminResource.java @@ -4,11 +4,10 @@ import org.jboss.logging.Logger; import org.jboss.resteasy.annotations.cache.NoCache; import org.jboss.resteasy.plugins.providers.multipart.InputPart; import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataInput; -import org.jboss.resteasy.spi.HttpRequest; import org.jboss.resteasy.spi.NotFoundException; import org.jboss.resteasy.spi.ResteasyProviderFactory; import org.keycloak.models.AdminRoles; -import org.keycloak.models.ApplicationModel; +import org.keycloak.models.ClientModel; import org.keycloak.models.KeycloakSession; import org.keycloak.models.ModelDuplicateException; import org.keycloak.models.RealmModel; @@ -75,27 +74,27 @@ public class RealmsAdminResource { */ @GET @NoCache - @Produces("application/json") + @Produces(MediaType.APPLICATION_JSON) public List getRealms() { RealmManager realmManager = new RealmManager(session); List reps = new ArrayList(); if (auth.getRealm().equals(realmManager.getKeycloakAdminstrationRealm())) { List realms = session.realms().getRealms(); for (RealmModel realm : realms) { - addRealmRep(reps, realm, realm.getMasterAdminApp()); + addRealmRep(reps, realm, realm.getMasterAdminClient()); } } else { - ApplicationModel adminApp = auth.getRealm().getApplicationByName(realmManager.getRealmAdminApplicationName(auth.getRealm())); + ClientModel adminApp = auth.getRealm().getClientByClientId(realmManager.getRealmAdminClientId(auth.getRealm())); addRealmRep(reps, auth.getRealm(), adminApp); } logger.debug(("getRealms()")); return reps; } - protected void addRealmRep(List reps, RealmModel realm, ApplicationModel realmManagementApplication) { - if (auth.hasAppRole(realmManagementApplication, AdminRoles.MANAGE_REALM)) { + protected void addRealmRep(List reps, RealmModel realm, ClientModel realmManagementClient) { + if (auth.hasAppRole(realmManagementClient, AdminRoles.MANAGE_REALM)) { reps.add(ModelToRepresentation.toRepresentation(realm, false)); - } else if (auth.hasOneOfAppRole(realmManagementApplication, AdminRoles.ALL_REALM_ROLES)) { + } else if (auth.hasOneOfAppRole(realmManagementClient, AdminRoles.ALL_REALM_ROLES)) { RealmRepresentation rep = new RealmRepresentation(); rep.setRealm(realm.getName()); reps.add(rep); @@ -110,7 +109,7 @@ public class RealmsAdminResource { * @return */ @POST - @Consumes("application/json") + @Consumes(MediaType.APPLICATION_JSON) public Response importRealm(@Context final UriInfo uriInfo, final RealmRepresentation rep) { RealmManager realmManager = new RealmManager(session); realmManager.setContextPath(keycloak.getContextPath()); @@ -187,7 +186,7 @@ public class RealmsAdminResource { } RealmModel adminRealm = new RealmManager(session).getKeycloakAdminstrationRealm(); - ApplicationModel realmAdminApp = realm.getMasterAdminApp(); + ClientModel realmAdminApp = realm.getMasterAdminClient(); for (String r : AdminRoles.ALL_REALM_ROLES) { RoleModel role = realmAdminApp.getRole(r); auth.getUser().grantRole(role); @@ -215,9 +214,9 @@ public class RealmsAdminResource { RealmAuth realmAuth; if (auth.getRealm().equals(realmManager.getKeycloakAdminstrationRealm())) { - realmAuth = new RealmAuth(auth, realm.getMasterAdminApp()); + realmAuth = new RealmAuth(auth, realm.getMasterAdminClient()); } else { - realmAuth = new RealmAuth(auth, realm.getApplicationByName(realmManager.getRealmAdminApplicationName(auth.getRealm()))); + realmAuth = new RealmAuth(auth, realm.getClientByClientId(realmManager.getRealmAdminClientId(auth.getRealm()))); } RealmAdminResource adminResource = new RealmAdminResource(realmAuth, realm, tokenManager); diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RoleByIdResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RoleByIdResource.java index 41ede41307..67d8c12e26 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/RoleByIdResource.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/RoleByIdResource.java @@ -3,9 +3,8 @@ package org.keycloak.services.resources.admin; import org.jboss.logging.Logger; import org.jboss.resteasy.annotations.cache.NoCache; import org.jboss.resteasy.spi.NotFoundException; -import org.keycloak.models.ApplicationModel; +import org.keycloak.models.ClientModel; import org.keycloak.models.KeycloakSession; -import org.keycloak.models.OAuthClientModel; import org.keycloak.models.RealmModel; import org.keycloak.models.RoleModel; import org.keycloak.models.UserModel; @@ -20,6 +19,7 @@ import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; import java.util.List; import java.util.Set; @@ -53,7 +53,7 @@ public class RoleByIdResource extends RoleResource { @Path("{role-id}") @GET @NoCache - @Produces("application/json") + @Produces(MediaType.APPLICATION_JSON) public RoleRepresentation getRole(final @PathParam("role-id") String id) { RoleModel roleModel = getRoleModel(id); auth.requireView(); @@ -70,9 +70,7 @@ public class RoleByIdResource extends RoleResource { RealmAuth.Resource r = null; if (roleModel.getContainer() instanceof RealmModel) { r = RealmAuth.Resource.REALM; - } else if (roleModel.getContainer() instanceof ApplicationModel) { - r = RealmAuth.Resource.APPLICATION; - } else if (roleModel.getContainer() instanceof OAuthClientModel) { + } else if (roleModel.getContainer() instanceof ClientModel) { r = RealmAuth.Resource.CLIENT; } else if (roleModel.getContainer() instanceof UserModel) { r = RealmAuth.Resource.USER; @@ -104,7 +102,7 @@ public class RoleByIdResource extends RoleResource { */ @Path("{role-id}") @PUT - @Consumes("application/json") + @Consumes(MediaType.APPLICATION_JSON) public void updateRole(final @PathParam("role-id") String id, final RoleRepresentation rep) { RoleModel role = getRoleModel(id); auth.requireManage(); @@ -119,7 +117,7 @@ public class RoleByIdResource extends RoleResource { */ @Path("{role-id}/composites") @POST - @Consumes("application/json") + @Consumes(MediaType.APPLICATION_JSON) public void addComposites(final @PathParam("role-id") String id, List roles) { RoleModel role = getRoleModel(id); auth.requireManage(); @@ -135,7 +133,7 @@ public class RoleByIdResource extends RoleResource { @Path("{role-id}/composites") @GET @NoCache - @Produces("application/json") + @Produces(MediaType.APPLICATION_JSON) public Set getRoleComposites(final @PathParam("role-id") String id) { if (logger.isDebugEnabled()) logger.debug("*** getRoleComposites: '" + id + "'"); @@ -153,7 +151,7 @@ public class RoleByIdResource extends RoleResource { @Path("{role-id}/composites/realm") @GET @NoCache - @Produces("application/json") + @Produces(MediaType.APPLICATION_JSON) public Set getRealmRoleComposites(final @PathParam("role-id") String id) { RoleModel role = getRoleModel(id); auth.requireView(); @@ -161,49 +159,49 @@ public class RoleByIdResource extends RoleResource { } /** - * Return a set of application-level roles for a specific app that are in the role's composite + * Return a set of client-level roles for a specific client that are in the role's composite * * @param id * @param appName * @return */ - @Path("{role-id}/composites/applications/{app}") + @Path("{role-id}/composites/clients/{app}") @GET @NoCache - @Produces("application/json") - public Set getApplicationRoleComposites(final @PathParam("role-id") String id, + @Produces(MediaType.APPLICATION_JSON) + public Set getClientRoleComposites(final @PathParam("role-id") String id, final @PathParam("app") String appName) { RoleModel role = getRoleModel(id); auth.requireView(); - ApplicationModel app = realm.getApplicationByName(appName); + ClientModel app = realm.getClientByClientId(appName); if (app == null) { - throw new NotFoundException("Could not find application: " + appName); + throw new NotFoundException("Could not find client: " + appName); } - return getApplicationRoleComposites(app, role); + return getClientRoleComposites(app, role); } /** - * Return a set of application-level roles for a specific app that are in the role's composite + * Return a set of client-level roles for a specific client that are in the role's composite * * @param id * @param appId * @return */ - @Path("{role-id}/composites/applications-by-id/{appId}") + @Path("{role-id}/composites/clients-by-id/{appId}") @GET @NoCache - @Produces("application/json") - public Set getApplicationByIdRoleComposites(final @PathParam("role-id") String id, + @Produces(MediaType.APPLICATION_JSON) + public Set getClientByIdRoleComposites(final @PathParam("role-id") String id, final @PathParam("appId") String appId) { RoleModel role = getRoleModel(id); auth.requireView(); - ApplicationModel app = realm.getApplicationById(appId); + ClientModel app = realm.getClientById(appId); if (app == null) { - throw new NotFoundException("Could not find application: " + appId); + throw new NotFoundException("Could not find client: " + appId); } - return getApplicationRoleComposites(app, role); + return getClientRoleComposites(app, role); } /** @@ -214,7 +212,7 @@ public class RoleByIdResource extends RoleResource { */ @Path("{role-id}/composites") @DELETE - @Consumes("application/json") + @Consumes(MediaType.APPLICATION_JSON) public void deleteComposites(final @PathParam("role-id") String id, List roles) { RoleModel role = getRoleModel(id); auth.requireManage(); diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RoleContainerResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RoleContainerResource.java index 3ddeafb5b7..66d37a9492 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/RoleContainerResource.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/RoleContainerResource.java @@ -2,7 +2,7 @@ package org.keycloak.services.resources.admin; import org.jboss.resteasy.annotations.cache.NoCache; import org.jboss.resteasy.spi.NotFoundException; -import org.keycloak.models.ApplicationModel; +import org.keycloak.models.ClientModel; import org.keycloak.models.ModelDuplicateException; import org.keycloak.models.RealmModel; import org.keycloak.models.RoleContainerModel; @@ -20,6 +20,7 @@ import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; import java.util.ArrayList; @@ -43,13 +44,13 @@ public class RoleContainerResource extends RoleResource { } /** - * List all roles for this realm or application + * List all roles for this realm or client * * @return */ @GET @NoCache - @Produces("application/json") + @Produces(MediaType.APPLICATION_JSON) public List getRoles() { auth.requireAny(); @@ -62,14 +63,14 @@ public class RoleContainerResource extends RoleResource { } /** - * Create a new role for this realm or application + * Create a new role for this realm or client * * @param uriInfo * @param rep * @return */ @POST - @Consumes("application/json") + @Consumes(MediaType.APPLICATION_JSON) public Response createRole(final @Context UriInfo uriInfo, final RoleRepresentation rep) { auth.requireManage(); @@ -91,7 +92,7 @@ public class RoleContainerResource extends RoleResource { @Path("{role-name}") @GET @NoCache - @Produces("application/json") + @Produces(MediaType.APPLICATION_JSON) public RoleRepresentation getRole(final @PathParam("role-name") String roleName) { auth.requireView(); @@ -131,7 +132,7 @@ public class RoleContainerResource extends RoleResource { */ @Path("{role-name}") @PUT - @Consumes("application/json") + @Consumes(MediaType.APPLICATION_JSON) public Response updateRole(final @PathParam("role-name") String roleName, final RoleRepresentation rep) { auth.requireManage(); @@ -155,7 +156,7 @@ public class RoleContainerResource extends RoleResource { */ @Path("{role-name}/composites") @POST - @Consumes("application/json") + @Consumes(MediaType.APPLICATION_JSON) public void addComposites(final @PathParam("role-name") String roleName, List roles) { auth.requireManage(); @@ -175,7 +176,7 @@ public class RoleContainerResource extends RoleResource { @Path("{role-name}/composites") @GET @NoCache - @Produces("application/json") + @Produces(MediaType.APPLICATION_JSON) public Set getRoleComposites(final @PathParam("role-name") String roleName) { auth.requireManage(); @@ -195,7 +196,7 @@ public class RoleContainerResource extends RoleResource { @Path("{role-name}/composites/realm") @GET @NoCache - @Produces("application/json") + @Produces(MediaType.APPLICATION_JSON) public Set getRealmRoleComposites(final @PathParam("role-name") String roleName) { auth.requireManage(); @@ -207,30 +208,30 @@ public class RoleContainerResource extends RoleResource { } /** - * An app-level roles for a specific app for this role's composite + * An client-level roles for a specific client for this role's composite * * @param roleName role's name (not id!) - * @param appName + * @param clientId * @return */ - @Path("{role-name}/composites/application/{app}") + @Path("{role-name}/composites/client/{clientId}") @GET @NoCache - @Produces("application/json") - public Set getApplicationRoleComposites(final @PathParam("role-name") String roleName, - final @PathParam("app") String appName) { + @Produces(MediaType.APPLICATION_JSON) + public Set getClientRoleComposites(final @PathParam("role-name") String roleName, + final @PathParam("clientId") String clientId) { auth.requireManage(); RoleModel role = roleContainer.getRole(roleName); if (role == null) { throw new NotFoundException("Could not find role: " + roleName); } - ApplicationModel app = realm.getApplicationByName(appName); + ClientModel app = realm.getClientByClientId(clientId); if (app == null) { - throw new NotFoundException("Could not find application: " + appName); + throw new NotFoundException("Could not find client: " + clientId); } - return getApplicationRoleComposites(app, role); + return getClientRoleComposites(app, role); } @@ -238,27 +239,27 @@ public class RoleContainerResource extends RoleResource { * An app-level roles for a specific app for this role's composite * * @param roleName role's name (not id!) - * @param appId + * @param id * @return */ - @Path("{role-name}/composites/application-by-id/{appId}") + @Path("{role-name}/composites/client-by-id/{id}") @GET @NoCache - @Produces("application/json") - public Set getApplicationByIdRoleComposites(final @PathParam("role-name") String roleName, - final @PathParam("appId") String appId) { + @Produces(MediaType.APPLICATION_JSON) + public Set getClientByIdRoleComposites(final @PathParam("role-name") String roleName, + final @PathParam("id") String id) { auth.requireManage(); RoleModel role = roleContainer.getRole(roleName); if (role == null) { throw new NotFoundException("Could not find role: " + roleName); } - ApplicationModel app = realm.getApplicationById(appId); - if (app == null) { - throw new NotFoundException("Could not find application: " + appId); + ClientModel client = realm.getClientById(id); + if (client == null) { + throw new NotFoundException("Could not find client: " + id); } - return getApplicationRoleComposites(app, role); + return getClientRoleComposites(client, role); } @@ -270,7 +271,7 @@ public class RoleContainerResource extends RoleResource { */ @Path("{role-name}/composites") @DELETE - @Consumes("application/json") + @Consumes(MediaType.APPLICATION_JSON) public void deleteComposites(final @PathParam("role-name") String roleName, List roles) { auth.requireManage(); diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RoleResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RoleResource.java index 8d6fd44ab4..8196528ccb 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/RoleResource.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/RoleResource.java @@ -1,7 +1,7 @@ package org.keycloak.services.resources.admin; import org.jboss.resteasy.spi.NotFoundException; -import org.keycloak.models.ApplicationModel; +import org.keycloak.models.ClientModel; import org.keycloak.models.RealmModel; import org.keycloak.models.RoleModel; import org.keycloak.models.utils.ModelToRepresentation; @@ -69,7 +69,7 @@ public abstract class RoleResource { return composites; } - protected Set getApplicationRoleComposites(ApplicationModel app, RoleModel role) { + protected Set getClientRoleComposites(ClientModel app, RoleModel role) { if (!role.isComposite() || role.getComposites().size() == 0) return Collections.emptySet(); Set composites = new HashSet(role.getComposites().size()); diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ScopeMappedApplicationResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ScopeMappedClientResource.java similarity index 59% rename from services/src/main/java/org/keycloak/services/resources/admin/ScopeMappedApplicationResource.java rename to services/src/main/java/org/keycloak/services/resources/admin/ScopeMappedClientResource.java index e61e6a05d3..01fe1d67ec 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/ScopeMappedApplicationResource.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/ScopeMappedClientResource.java @@ -2,7 +2,6 @@ package org.keycloak.services.resources.admin; import org.jboss.resteasy.annotations.cache.NoCache; import org.jboss.resteasy.spi.NotFoundException; -import org.keycloak.models.ApplicationModel; import org.keycloak.models.ClientModel; import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; @@ -15,8 +14,8 @@ import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.Path; -import javax.ws.rs.PathParam; import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; import java.util.ArrayList; import java.util.List; import java.util.Set; @@ -25,33 +24,33 @@ import java.util.Set; * @author Bill Burke * @version $Revision: 1 $ */ -public class ScopeMappedApplicationResource { +public class ScopeMappedClientResource { protected RealmModel realm; private RealmAuth auth; protected ClientModel client; protected KeycloakSession session; - protected ApplicationModel app; + protected ClientModel scopedClient; - public ScopeMappedApplicationResource(RealmModel realm, RealmAuth auth, ClientModel client, KeycloakSession session, ApplicationModel app) { + public ScopeMappedClientResource(RealmModel realm, RealmAuth auth, ClientModel client, KeycloakSession session, ClientModel scopedClient) { this.realm = realm; this.auth = auth; this.client = client; this.session = session; - this.app = app; + this.scopedClient = scopedClient; } /** - * Get the roles associated with a client's scope for a specific application. + * Get the roles associated with a client's scope for a specific client. * * @return */ @GET - @Produces("application/json") + @Produces(MediaType.APPLICATION_JSON) @NoCache - public List getApplicationScopeMappings() { + public List getClientScopeMappings() { auth.requireView(); - Set mappings = app.getApplicationScopeMappings(client); + Set mappings = scopedClient.getClientScopeMappings(client); List mapRep = new ArrayList(); for (RoleModel roleModel : mappings) { mapRep.add(ModelToRepresentation.toRepresentation(roleModel)); @@ -60,49 +59,49 @@ public class ScopeMappedApplicationResource { } /** - * The available application-level roles that can be associated with the client's scope + * The available client-level roles that can be associated with the client's scope * * @return */ @Path("available") @GET - @Produces("application/json") + @Produces(MediaType.APPLICATION_JSON) @NoCache - public List getAvailableApplicationScopeMappings() { + public List getAvailableClientScopeMappings() { auth.requireView(); - Set roles = app.getRoles(); + Set roles = scopedClient.getRoles(); return ScopeMappedResource.getAvailable(client, roles); } /** - * Get effective application roles that are associated with the client's scope for a specific application. + * Get effective client roles that are associated with the client's scope for a specific client. * * @return */ @Path("composite") @GET - @Produces("application/json") + @Produces(MediaType.APPLICATION_JSON) @NoCache - public List getCompositeApplicationScopeMappings() { + public List getCompositeClientScopeMappings() { auth.requireView(); - Set roles = app.getRoles(); + Set roles = scopedClient.getRoles(); return ScopeMappedResource.getComposite(client, roles); } /** - * Add application-level roles to the client's scope + * Add client-level roles to the client's scope * * @param roles */ @POST - @Consumes("application/json") - public void addApplicationScopeMapping(List roles) { + @Consumes(MediaType.APPLICATION_JSON) + public void addClientScopeMapping(List roles) { auth.requireManage(); for (RoleRepresentation role : roles) { - RoleModel roleModel = app.getRole(role.getName()); + RoleModel roleModel = scopedClient.getRole(role.getName()); if (roleModel == null) { throw new NotFoundException("Role not found"); } @@ -112,24 +111,24 @@ public class ScopeMappedApplicationResource { } /** - * Remove application-level roles from the client's scope. + * Remove client-level roles from the client's scope. * * @param roles */ @DELETE - @Consumes("application/json") - public void deleteApplicationScopeMapping(List roles) { + @Consumes(MediaType.APPLICATION_JSON) + public void deleteClientScopeMapping(List roles) { auth.requireManage(); if (roles == null) { - Set roleModels = app.getApplicationScopeMappings(client); + Set roleModels = scopedClient.getClientScopeMappings(client); for (RoleModel roleModel : roleModels) { client.deleteScopeMapping(roleModel); } } else { for (RoleRepresentation role : roles) { - RoleModel roleModel = app.getRole(role.getName()); + RoleModel roleModel = scopedClient.getRole(role.getName()); if (roleModel == null) { throw new NotFoundException("Role not found"); } diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ScopeMappedResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ScopeMappedResource.java index 8084c44a57..8d4e005710 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/ScopeMappedResource.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/ScopeMappedResource.java @@ -2,13 +2,12 @@ package org.keycloak.services.resources.admin; import org.jboss.resteasy.annotations.cache.NoCache; import org.jboss.resteasy.spi.NotFoundException; -import org.keycloak.models.ApplicationModel; import org.keycloak.models.ClientModel; import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; import org.keycloak.models.RoleModel; import org.keycloak.models.utils.ModelToRepresentation; -import org.keycloak.representations.idm.ApplicationMappingsRepresentation; +import org.keycloak.representations.idm.ClientMappingsRepresentation; import org.keycloak.representations.idm.MappingsRepresentation; import org.keycloak.representations.idm.RoleRepresentation; @@ -19,6 +18,7 @@ import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -26,7 +26,7 @@ import java.util.Map; import java.util.Set; /** - * Base class for managing the scope mappings of a specific client (application or oauth). + * Base class for managing the scope mappings of a specific client. * * @author Bill Burke * @version $Revision: 1 $ @@ -50,7 +50,7 @@ public class ScopeMappedResource { * @return */ @GET - @Produces("application/json") + @Produces(MediaType.APPLICATION_JSON) @NoCache public MappingsRepresentation getScopeMappings() { auth.requireView(); @@ -65,22 +65,22 @@ public class ScopeMappedResource { all.setRealmMappings(realmRep); } - List applications = realm.getApplications(); - if (applications.size() > 0) { - Map appMappings = new HashMap(); - for (ApplicationModel app : applications) { - Set roleMappings = app.getApplicationScopeMappings(client); + List clients = realm.getClients(); + if (clients.size() > 0) { + Map clientMappings = new HashMap(); + for (ClientModel client : clients) { + Set roleMappings = client.getClientScopeMappings(this.client); if (roleMappings.size() > 0) { - ApplicationMappingsRepresentation mappings = new ApplicationMappingsRepresentation(); - mappings.setApplicationId(app.getId()); - mappings.setApplication(app.getName()); + ClientMappingsRepresentation mappings = new ClientMappingsRepresentation(); + mappings.setId(client.getId()); + mappings.setClient(client.getClientId()); List roles = new ArrayList(); mappings.setMappings(roles); for (RoleModel role : roleMappings) { roles.add(ModelToRepresentation.toRepresentation(role)); } - appMappings.put(app.getName(), mappings); - all.setApplicationMappings(appMappings); + clientMappings.put(client.getClientId(), mappings); + all.setClientMappings(clientMappings); } } } @@ -94,7 +94,7 @@ public class ScopeMappedResource { */ @Path("realm") @GET - @Produces("application/json") + @Produces(MediaType.APPLICATION_JSON) @NoCache public List getRealmScopeMappings() { auth.requireView(); @@ -114,7 +114,7 @@ public class ScopeMappedResource { */ @Path("realm/available") @GET - @Produces("application/json") + @Produces(MediaType.APPLICATION_JSON) @NoCache public List getAvailableRealmScopeMappings() { auth.requireView(); @@ -141,7 +141,7 @@ public class ScopeMappedResource { */ @Path("realm/composite") @GET - @Produces("application/json") + @Produces(MediaType.APPLICATION_JSON) @NoCache public List getCompositeRealmScopeMappings() { auth.requireView(); @@ -165,7 +165,7 @@ public class ScopeMappedResource { */ @Path("realm") @POST - @Consumes("application/json") + @Consumes(MediaType.APPLICATION_JSON) public void addRealmScopeMappings(List roles) { auth.requireManage(); @@ -187,7 +187,7 @@ public class ScopeMappedResource { */ @Path("realm") @DELETE - @Consumes("application/json") + @Consumes(MediaType.APPLICATION_JSON) public void deleteRealmScopeMappings(List roles) { auth.requireManage(); @@ -201,32 +201,32 @@ public class ScopeMappedResource { for (RoleRepresentation role : roles) { RoleModel roleModel = realm.getRoleById(role.getId()); if (roleModel == null) { - throw new NotFoundException("Application not found"); + throw new NotFoundException("Client not found"); } client.deleteScopeMapping(roleModel); } } } - @Path("applications/{app}") - public ScopeMappedApplicationResource getApplicationScopeMappings(@PathParam("app") String appName) { - ApplicationModel app = realm.getApplicationByName(appName); + @Path("clients/{clientId}") + public ScopeMappedClientResource getClientScopeMappings(@PathParam("clientId") String clientId) { + ClientModel app = realm.getClientByClientId(clientId); if (app == null) { throw new NotFoundException("Role not found"); } - return new ScopeMappedApplicationResource(realm, auth, client, session, app); + return new ScopeMappedClientResource(realm, auth, client, session, app); } - @Path("applications-by-id/{appId}") - public ScopeMappedApplicationResource getApplicationByIdScopeMappings(@PathParam("appId") String appId) { - ApplicationModel app = realm.getApplicationById(appId); + @Path("clients-by-id/{id}") + public ScopeMappedClientResource getClientByIdScopeMappings(@PathParam("id") String id) { + ClientModel app = realm.getClientById(id); if (app == null) { - throw new NotFoundException("Application not found"); + throw new NotFoundException("Client not found"); } - return new ScopeMappedApplicationResource(realm, auth, client, session, app); + return new ScopeMappedClientResource(realm, auth, client, session, app); } } diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ServerInfoAdminResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ServerInfoAdminResource.java index acaa0b84d7..0bdb525d5f 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/ServerInfoAdminResource.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/ServerInfoAdminResource.java @@ -5,8 +5,8 @@ import org.keycloak.broker.provider.IdentityProvider; import org.keycloak.broker.provider.IdentityProviderFactory; import org.keycloak.events.EventListenerProvider; import org.keycloak.events.EventType; -import org.keycloak.exportimport.ApplicationImporter; -import org.keycloak.exportimport.ApplicationImporterFactory; +import org.keycloak.exportimport.ClientImporter; +import org.keycloak.exportimport.ClientImporterFactory; import org.keycloak.freemarker.Theme; import org.keycloak.freemarker.ThemeProvider; import org.keycloak.models.KeycloakSession; @@ -56,7 +56,7 @@ public class ServerInfoAdminResource { setThemes(info); setEventListeners(info); setProtocols(info); - setApplicationImporters(info); + setClientImporters(info); setProviders(info); setProtocolMapperTypes(info); setBuiltinProtocolMappers(info); @@ -168,14 +168,14 @@ public class ServerInfoAdminResource { } } - private void setApplicationImporters(ServerInfoRepresentation info) { - info.applicationImporters = new LinkedList>(); - for (ProviderFactory p : session.getKeycloakSessionFactory().getProviderFactories(ApplicationImporter.class)) { - ApplicationImporterFactory factory = (ApplicationImporterFactory)p; + private void setClientImporters(ServerInfoRepresentation info) { + info.clientImporters = new LinkedList>(); + for (ProviderFactory p : session.getKeycloakSessionFactory().getProviderFactories(ClientImporter.class)) { + ClientImporterFactory factory = (ClientImporterFactory)p; Map data = new HashMap(); data.put("id", factory.getId()); data.put("name", factory.getDisplayName()); - info.applicationImporters.add(data); + info.clientImporters.add(data); } } @@ -199,7 +199,7 @@ public class ServerInfoAdminResource { private List> socialProviders; public List> identityProviders; private List protocols; - private List> applicationImporters; + private List> clientImporters; private Map> providers; @@ -240,8 +240,8 @@ public class ServerInfoAdminResource { return protocols; } - public List> getApplicationImporters() { - return applicationImporters; + public List> getClientImporters() { + return clientImporters; } public Map> getProviders() { diff --git a/services/src/main/java/org/keycloak/services/resources/admin/UserApplicationRoleMappingsResource.java b/services/src/main/java/org/keycloak/services/resources/admin/UserClientRoleMappingsResource.java similarity index 55% rename from services/src/main/java/org/keycloak/services/resources/admin/UserApplicationRoleMappingsResource.java rename to services/src/main/java/org/keycloak/services/resources/admin/UserClientRoleMappingsResource.java index 4c5b7d6a7e..e838333c61 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/UserApplicationRoleMappingsResource.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/UserClientRoleMappingsResource.java @@ -3,14 +3,11 @@ package org.keycloak.services.resources.admin; import org.jboss.logging.Logger; import org.jboss.resteasy.annotations.cache.NoCache; import org.jboss.resteasy.spi.NotFoundException; -import org.keycloak.ClientConnection; -import org.keycloak.models.ApplicationModel; -import org.keycloak.models.KeycloakSession; +import org.keycloak.models.ClientModel; import org.keycloak.models.RealmModel; import org.keycloak.models.RoleModel; import org.keycloak.models.UserModel; import org.keycloak.models.utils.ModelToRepresentation; -import org.keycloak.protocol.oidc.TokenManager; import org.keycloak.representations.idm.RoleRepresentation; import javax.ws.rs.Consumes; @@ -18,10 +15,8 @@ import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.Path; -import javax.ws.rs.PathParam; import javax.ws.rs.Produces; -import javax.ws.rs.core.Context; -import javax.ws.rs.core.UriInfo; +import javax.ws.rs.core.MediaType; import java.util.ArrayList; import java.util.HashSet; import java.util.List; @@ -31,79 +26,73 @@ import java.util.Set; * @author Bill Burke * @version $Revision: 1 $ */ -public class UserApplicationRoleMappingsResource { - protected static final Logger logger = Logger.getLogger(UserApplicationRoleMappingsResource.class); +public class UserClientRoleMappingsResource { + protected static final Logger logger = Logger.getLogger(UserClientRoleMappingsResource.class); protected RealmModel realm; protected RealmAuth auth; protected UserModel user; - protected ApplicationModel application; + protected ClientModel client; - public UserApplicationRoleMappingsResource(RealmModel realm, RealmAuth auth, UserModel user, ApplicationModel application) { + public UserClientRoleMappingsResource(RealmModel realm, RealmAuth auth, UserModel user, ClientModel client) { this.realm = realm; this.auth = auth; this.user = user; - this.application = application; + this.client = client; } /** - * Get application-level role mappings for this user for a specific app + * Get client-level role mappings for this user for a specific app * * @return */ @GET - @Produces("application/json") + @Produces(MediaType.APPLICATION_JSON) @NoCache - public List getApplicationRoleMappings() { + public List getClientRoleMappings() { auth.requireView(); - logger.debug("getApplicationRoleMappings"); - - Set mappings = user.getApplicationRoleMappings(application); + Set mappings = user.getClientRoleMappings(client); List mapRep = new ArrayList(); for (RoleModel roleModel : mappings) { mapRep.add(ModelToRepresentation.toRepresentation(roleModel)); } - logger.debugv("getApplicationRoleMappings.size() = {0}", mapRep.size()); return mapRep; } /** - * Get effective application-level role mappings. This recurses any composite roles + * Get effective client-level role mappings. This recurses any composite roles * * @return */ @Path("composite") @GET - @Produces("application/json") + @Produces(MediaType.APPLICATION_JSON) @NoCache - public List getCompositeApplicationRoleMappings() { + public List getCompositeClientRoleMappings() { auth.requireView(); - logger.debug("getCompositeApplicationRoleMappings"); - - Set roles = application.getRoles(); + Set roles = client.getRoles(); List mapRep = new ArrayList(); for (RoleModel roleModel : roles) { if (user.hasRole(roleModel)) mapRep.add(ModelToRepresentation.toRepresentation(roleModel)); } - logger.debugv("getCompositeApplicationRoleMappings.size() = {0}", mapRep.size()); return mapRep; } /** - * Get available application-level roles that can be mapped to the user + * Get available client-level roles that can be mapped to the user * * @return */ @Path("available") @GET - @Produces("application/json") + @Produces(MediaType.APPLICATION_JSON) @NoCache - public List getAvailableApplicationRoleMappings() { + public List getAvailableClientRoleMappings() { auth.requireView(); - Set available = application.getRoles(); + Set available = client.getRoles(); return getAvailableRoles(user, available); } @@ -122,18 +111,17 @@ public class UserApplicationRoleMappingsResource { } /** - * Add application-level roles to the user role mapping. + * Add client-level roles to the user role mapping. * * @param roles */ @POST - @Consumes("application/json") - public void addApplicationRoleMapping(List roles) { + @Consumes(MediaType.APPLICATION_JSON) + public void addClientRoleMapping(List roles) { auth.requireManage(); - logger.debug("addApplicationRoleMapping"); for (RoleRepresentation role : roles) { - RoleModel roleModel = application.getRole(role.getName()); + RoleModel roleModel = client.getRole(role.getName()); if (roleModel == null || !roleModel.getId().equals(role.getId())) { throw new NotFoundException("Role not found"); } @@ -143,28 +131,28 @@ public class UserApplicationRoleMappingsResource { } /** - * Delete application-level roles from user role mapping. + * Delete client-level roles from user role mapping. * * @param roles */ @DELETE - @Consumes("application/json") - public void deleteApplicationRoleMapping(List roles) { + @Consumes(MediaType.APPLICATION_JSON) + public void deleteClientRoleMapping(List roles) { auth.requireManage(); if (roles == null) { - Set roleModels = user.getApplicationRoleMappings(application); + Set roleModels = user.getClientRoleMappings(client); for (RoleModel roleModel : roleModels) { - if (!(roleModel.getContainer() instanceof ApplicationModel)) { - ApplicationModel app = (ApplicationModel) roleModel.getContainer(); - if (!app.getId().equals(application.getId())) continue; + if (!(roleModel.getContainer() instanceof ClientModel)) { + ClientModel client = (ClientModel) roleModel.getContainer(); + if (!client.getId().equals(this.client.getId())) continue; } user.deleteRoleMapping(roleModel); } } else { for (RoleRepresentation role : roles) { - RoleModel roleModel = application.getRole(role.getName()); + RoleModel roleModel = client.getRole(role.getName()); if (roleModel == null || !roleModel.getId().equals(role.getId())) { throw new NotFoundException("Role not found"); } diff --git a/services/src/main/java/org/keycloak/services/resources/admin/UserFederationResource.java b/services/src/main/java/org/keycloak/services/resources/admin/UserFederationResource.java index 006124bc15..188cb30ae3 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/UserFederationResource.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/UserFederationResource.java @@ -28,6 +28,7 @@ import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; import java.util.LinkedList; @@ -67,7 +68,7 @@ public class UserFederationResource { @GET @NoCache @Path("providers") - @Produces("application/json") + @Produces(MediaType.APPLICATION_JSON) public List getProviders() { auth.requireView(); List providers = new LinkedList(); @@ -88,7 +89,7 @@ public class UserFederationResource { @GET @NoCache @Path("providers/{id}") - @Produces("application/json") + @Produces(MediaType.APPLICATION_JSON) public UserFederationProviderFactoryRepresentation getProvider(@PathParam("id") String id) { auth.requireView(); for (ProviderFactory factory : session.getKeycloakSessionFactory().getProviderFactories(UserFederationProvider.class)) { @@ -111,7 +112,7 @@ public class UserFederationResource { */ @POST @Path("instances") - @Consumes("application/json") + @Consumes(MediaType.APPLICATION_JSON) public Response createProviderInstance(UserFederationProviderRepresentation rep) { auth.requireManage(); String displayName = rep.getDisplayName(); @@ -133,7 +134,7 @@ public class UserFederationResource { */ @PUT @Path("instances/{id}") - @Consumes("application/json") + @Consumes(MediaType.APPLICATION_JSON) public void updateProviderInstance(@PathParam("id") String id, UserFederationProviderRepresentation rep) { auth.requireManage(); String displayName = rep.getDisplayName(); @@ -155,7 +156,7 @@ public class UserFederationResource { @GET @NoCache @Path("instances/{id}") - @Produces("application/json") + @Produces(MediaType.APPLICATION_JSON) public UserFederationProviderRepresentation getProviderInstance(@PathParam("id") String id) { auth.requireView(); for (UserFederationProviderModel model : realm.getUserFederationProviders()) { @@ -191,7 +192,7 @@ public class UserFederationResource { */ @GET @Path("instances") - @Produces("application/json") + @Produces(MediaType.APPLICATION_JSON) @NoCache public List getUserFederationInstances() { auth.requireManage(); diff --git a/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java b/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java index ff5370ba47..8bad8982ef 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java @@ -7,7 +7,6 @@ import org.jboss.resteasy.spi.NotFoundException; import org.keycloak.ClientConnection; import org.keycloak.email.EmailException; import org.keycloak.email.EmailProvider; -import org.keycloak.models.ApplicationModel; import org.keycloak.models.ClientModel; import org.keycloak.models.ClientSessionModel; import org.keycloak.models.Constants; @@ -26,7 +25,7 @@ import org.keycloak.models.utils.RepresentationToModel; import org.keycloak.protocol.oidc.OIDCLoginProtocol; import org.keycloak.protocol.oidc.TokenManager; import org.keycloak.protocol.oidc.utils.RedirectUtils; -import org.keycloak.representations.idm.ApplicationMappingsRepresentation; +import org.keycloak.representations.idm.ClientMappingsRepresentation; import org.keycloak.representations.idm.CredentialRepresentation; import org.keycloak.representations.idm.FederatedIdentityRepresentation; import org.keycloak.representations.idm.MappingsRepresentation; @@ -107,7 +106,7 @@ public class UsersResource { */ @Path("{username}") @PUT - @Consumes("application/json") + @Consumes(MediaType.APPLICATION_JSON) public Response updateUser(final @PathParam("username") String username, final UserRepresentation rep) { auth.requireManage(); @@ -138,7 +137,7 @@ public class UsersResource { * @return */ @POST - @Consumes("application/json") + @Consumes(MediaType.APPLICATION_JSON) public Response createUser(final @Context UriInfo uriInfo, final UserRepresentation rep) { auth.requireManage(); @@ -210,7 +209,7 @@ public class UsersResource { @Path("{username}") @GET @NoCache - @Produces("application/json") + @Produces(MediaType.APPLICATION_JSON) public UserRepresentation getUser(final @PathParam("username") String username) { auth.requireView(); @@ -312,7 +311,7 @@ public class UsersResource { } /** - * Remove all user sessions associated with this user. And, for all applications that have an admin URL, tell + * Remove all user sessions associated with this user. And, for all client that have an admin URL, tell * them to invalidate the sessions for this particular user. * * @param username username (not id!) @@ -369,7 +368,7 @@ public class UsersResource { */ @GET @NoCache - @Produces("application/json") + @Produces(MediaType.APPLICATION_JSON) public List getUsers(@QueryParam("search") String search, @QueryParam("lastName") String last, @QueryParam("firstName") String first, @@ -419,7 +418,7 @@ public class UsersResource { */ @Path("{username}/role-mappings") @GET - @Produces("application/json") + @Produces(MediaType.APPLICATION_JSON) @NoCache public MappingsRepresentation getRoleMappings(@PathParam("username") String username) { auth.requireView(); @@ -440,22 +439,22 @@ public class UsersResource { all.setRealmMappings(realmRep); } - List applications = realm.getApplications(); - if (applications.size() > 0) { - Map appMappings = new HashMap(); - for (ApplicationModel application : applications) { - Set roleMappings = user.getApplicationRoleMappings(application); + List clients = realm.getClients(); + if (clients.size() > 0) { + Map appMappings = new HashMap(); + for (ClientModel client : clients) { + Set roleMappings = user.getClientRoleMappings(client); if (roleMappings.size() > 0) { - ApplicationMappingsRepresentation mappings = new ApplicationMappingsRepresentation(); - mappings.setApplicationId(application.getId()); - mappings.setApplication(application.getName()); + ClientMappingsRepresentation mappings = new ClientMappingsRepresentation(); + mappings.setId(client.getId()); + mappings.setClient(client.getClientId()); List roles = new ArrayList(); mappings.setMappings(roles); for (RoleModel role : roleMappings) { roles.add(ModelToRepresentation.toRepresentation(role)); } - appMappings.put(application.getName(), mappings); - all.setApplicationMappings(appMappings); + appMappings.put(client.getClientId(), mappings); + all.setClientMappings(appMappings); } } } @@ -470,7 +469,7 @@ public class UsersResource { */ @Path("{username}/role-mappings/realm") @GET - @Produces("application/json") + @Produces(MediaType.APPLICATION_JSON) @NoCache public List getRealmRoleMappings(@PathParam("username") String username) { auth.requireView(); @@ -496,7 +495,7 @@ public class UsersResource { */ @Path("{username}/role-mappings/realm/composite") @GET - @Produces("application/json") + @Produces(MediaType.APPLICATION_JSON) @NoCache public List getCompositeRealmRoleMappings(@PathParam("username") String username) { auth.requireView(); @@ -524,7 +523,7 @@ public class UsersResource { */ @Path("{username}/role-mappings/realm/available") @GET - @Produces("application/json") + @Produces(MediaType.APPLICATION_JSON) @NoCache public List getAvailableRealmRoleMappings(@PathParam("username") String username) { auth.requireView(); @@ -535,7 +534,7 @@ public class UsersResource { } Set available = realm.getRoles(); - return UserApplicationRoleMappingsResource.getAvailableRoles(user, available); + return UserClientRoleMappingsResource.getAvailableRoles(user, available); } /** @@ -546,7 +545,7 @@ public class UsersResource { */ @Path("{username}/role-mappings/realm") @POST - @Consumes("application/json") + @Consumes(MediaType.APPLICATION_JSON) public void addRealmRoleMappings(@PathParam("username") String username, List roles) { auth.requireManage(); @@ -575,7 +574,7 @@ public class UsersResource { */ @Path("{username}/role-mappings/realm") @DELETE - @Consumes("application/json") + @Consumes(MediaType.APPLICATION_JSON) public void deleteRealmRoleMappings(@PathParam("username") String username, List roles) { auth.requireManage(); @@ -602,36 +601,36 @@ public class UsersResource { } } - @Path("{username}/role-mappings/applications/{app}") - public UserApplicationRoleMappingsResource getUserApplicationRoleMappingsResource(@PathParam("username") String username, @PathParam("app") String appName) { + @Path("{username}/role-mappings/clients/{clientId}") + public UserClientRoleMappingsResource getUserClientRoleMappingsResource(@PathParam("username") String username, @PathParam("clientId") String clientId) { UserModel user = session.users().getUserByUsername(username, realm); if (user == null) { throw new NotFoundException("User not found"); } - ApplicationModel application = realm.getApplicationByName(appName); + ClientModel client = realm.getClientByClientId(clientId); - if (application == null) { - throw new NotFoundException("Application not found"); + if (client == null) { + throw new NotFoundException("Client not found"); } - return new UserApplicationRoleMappingsResource(realm, auth, user, application); + return new UserClientRoleMappingsResource(realm, auth, user, client); } - @Path("{username}/role-mappings/applications-by-id/{appId}") - public UserApplicationRoleMappingsResource getUserApplicationRoleMappingsResourceById(@PathParam("username") String username, @PathParam("appId") String appId) { + @Path("{username}/role-mappings/clients-by-id/{id}") + public UserClientRoleMappingsResource getUserClientRoleMappingsResourceById(@PathParam("username") String username, @PathParam("id") String id) { UserModel user = session.users().getUserByUsername(username, realm); if (user == null) { throw new NotFoundException("User not found"); } - ApplicationModel application = realm.getApplicationById(appId); + ClientModel client = realm.getClientById(id); - if (application == null) { - throw new NotFoundException("Application not found"); + if (client == null) { + throw new NotFoundException("Client not found"); } - return new UserApplicationRoleMappingsResource(realm, auth, user, application); + return new UserClientRoleMappingsResource(realm, auth, user, client); } /** @@ -643,7 +642,7 @@ public class UsersResource { */ @Path("{username}/reset-password") @PUT - @Consumes("application/json") + @Consumes(MediaType.APPLICATION_JSON) public void resetPassword(@PathParam("username") String username, CredentialRepresentation pass) { auth.requireManage(); @@ -671,7 +670,7 @@ public class UsersResource { */ @Path("{username}/remove-totp") @PUT - @Consumes("application/json") + @Consumes(MediaType.APPLICATION_JSON) public void removeTotp(@PathParam("username") String username) { auth.requireManage(); @@ -686,7 +685,7 @@ public class UsersResource { /** * Send an email to the user with a link they can click to reset their password. * The redirectUri and clientId parameters are optional. The default for the - * redirect is the account application. + * redirect is the account client. * * @param username username (not id!) * @param redirectUri redirect uri @@ -695,7 +694,7 @@ public class UsersResource { */ @Path("{username}/reset-password-email") @PUT - @Consumes("application/json") + @Consumes(MediaType.APPLICATION_JSON) public Response resetPasswordEmail(@PathParam("username") String username, @QueryParam(OIDCLoginProtocol.REDIRECT_URI_PARAM) String redirectUri, @QueryParam(OIDCLoginProtocol.CLIENT_ID_PARAM) String clientId) { auth.requireManage(); @@ -717,10 +716,10 @@ public class UsersResource { } if(clientId == null){ - clientId = Constants.ACCOUNT_MANAGEMENT_APP; + clientId = Constants.ACCOUNT_MANAGEMENT_CLIENT_ID; } - ClientModel client = realm.findClient(clientId); + ClientModel client = realm.getClientByClientId(clientId); if (client == null || !client.isEnabled()) { return Flows.errors().error(clientId + " not enabled", Response.Status.INTERNAL_SERVER_ERROR); } diff --git a/services/src/main/resources/META-INF/services/org.keycloak.provider.Spi b/services/src/main/resources/META-INF/services/org.keycloak.provider.Spi index cb0145565e..e1c0b91282 100755 --- a/services/src/main/resources/META-INF/services/org.keycloak.provider.Spi +++ b/services/src/main/resources/META-INF/services/org.keycloak.provider.Spi @@ -1,4 +1,4 @@ org.keycloak.protocol.LoginProtocolSpi org.keycloak.protocol.ProtocolMapperSpi -org.keycloak.exportimport.ApplicationImportSpi +org.keycloak.exportimport.ClientImportSpi org.keycloak.wellknown.WellKnownSpi \ No newline at end of file diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/account/AccountTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/account/AccountTest.java index ce61d3351c..999fdb875f 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/account/AccountTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/account/AccountTest.java @@ -25,13 +25,12 @@ import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.ClassRule; -import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.keycloak.events.Details; import org.keycloak.events.Event; import org.keycloak.events.EventType; -import org.keycloak.models.ApplicationModel; +import org.keycloak.models.ClientModel; import org.keycloak.models.PasswordPolicy; import org.keycloak.models.RealmModel; import org.keycloak.models.UserCredentialModel; @@ -75,7 +74,7 @@ public class AccountTest { public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) { UserModel user = manager.getSession().users().getUserByUsername("test-user@localhost", appRealm); - ApplicationModel accountApp = appRealm.getApplicationNameMap().get(org.keycloak.models.Constants.ACCOUNT_MANAGEMENT_APP); + ClientModel accountApp = appRealm.getClientNameMap().get(org.keycloak.models.Constants.ACCOUNT_MANAGEMENT_CLIENT_ID); UserModel user2 = manager.getSession().users().addUser(appRealm, "test-user-no-access@localhost"); user2.setEnabled(true); @@ -157,11 +156,6 @@ public class AccountTest { }); } - //@Test @Ignore - public void runit() throws Exception { - Thread.sleep(10000000); - } - @Test public void returnToAppFromQueryParam() { driver.navigate().to(AccountUpdateProfilePage.PATH + "?referrer=test-app"); diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/account/ProfileTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/account/ProfileTest.java index 97e2095f3e..44ebaf1712 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/account/ProfileTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/account/ProfileTest.java @@ -12,7 +12,6 @@ import org.junit.Rule; import org.junit.Test; import org.keycloak.OAuth2Constants; import org.keycloak.models.AccountRoles; -import org.keycloak.models.ApplicationModel; import org.keycloak.models.ClientModel; import org.keycloak.models.RealmModel; import org.keycloak.models.UserCredentialModel; @@ -54,7 +53,7 @@ public class ProfileTest { user.setAttribute("key1", "value1"); user.setAttribute("key2", "value2"); - ApplicationModel accountApp = appRealm.getApplicationByName(org.keycloak.models.Constants.ACCOUNT_MANAGEMENT_APP); + ClientModel accountApp = appRealm.getClientByClientId(org.keycloak.models.Constants.ACCOUNT_MANAGEMENT_CLIENT_ID); UserModel user2 = manager.getSession().users().addUser(appRealm, "test-user-no-access@localhost"); user2.setEnabled(true); @@ -66,12 +65,12 @@ public class ProfileTest { creds.setValue("password"); user2.updateCredential(creds); - ApplicationModel app = appRealm.getApplicationByName("test-app"); + ClientModel app = appRealm.getClientByClientId("test-app"); app.addScopeMapping(accountApp.getRole(AccountRoles.VIEW_PROFILE)); app.addRedirectUri("http://localhost:8081/app/*"); app.addWebOrigin("http://localtest.me:8081"); - ClientModel thirdParty = appRealm.findClient("third-party"); + ClientModel thirdParty = appRealm.getClientByClientId("third-party"); thirdParty.addScopeMapping(accountApp.getRole(AccountRoles.VIEW_PROFILE)); } }); diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTestStrategy.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTestStrategy.java index 8feaac569e..ba41ceb4f1 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTestStrategy.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTestStrategy.java @@ -22,14 +22,13 @@ package org.keycloak.testsuite.adapter; import org.junit.Assert; -import org.junit.Test; import org.junit.rules.ExternalResource; import org.keycloak.Config; import org.keycloak.OAuth2Constants; import org.keycloak.Version; import org.keycloak.admin.client.Keycloak; import org.keycloak.constants.AdapterConstants; -import org.keycloak.models.ApplicationModel; +import org.keycloak.models.ClientModel; import org.keycloak.models.ClientSessionModel; import org.keycloak.models.Constants; import org.keycloak.models.KeycloakSession; @@ -41,7 +40,6 @@ import org.keycloak.protocol.oidc.OIDCLoginProtocolService; import org.keycloak.protocol.oidc.TokenManager; import org.keycloak.representations.AccessToken; import org.keycloak.representations.idm.RealmRepresentation; -import org.keycloak.services.managers.AuthenticationManager; import org.keycloak.services.managers.RealmManager; import org.keycloak.services.managers.ResourceAdminManager; import org.keycloak.services.resources.admin.AdminRoot; @@ -65,7 +63,6 @@ import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriBuilder; import java.net.URI; -import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; @@ -139,7 +136,7 @@ public class AdapterTestStrategy extends ExternalResource { RealmManager manager = new RealmManager(session); RealmModel adminRealm = manager.getRealm(Config.getAdminRealm()); - ApplicationModel adminConsole = adminRealm.getApplicationByName(Constants.ADMIN_CONSOLE_APPLICATION); + ClientModel adminConsole = adminRealm.getClientByClientId(Constants.ADMIN_CONSOLE_CLIENT_ID); TokenManager tm = new TokenManager(); UserModel admin = session.users().getUserByUsername("admin", adminRealm); ClientSessionModel clientSession = session.sessions().createClientSession(adminRealm, adminConsole); @@ -152,7 +149,6 @@ public class AdapterTestStrategy extends ExternalResource { } } - @Test public void testSavedPostRequest() throws Exception { // test login to customer-portal which does a bearer request to customer-db driver.navigate().to(APP_SERVER_BASE_URL + "/input-portal"); @@ -191,7 +187,6 @@ public class AdapterTestStrategy extends ExternalResource { } - @Test public void testLoginSSOAndLogout() throws Exception { // test login to customer-portal which does a bearer request to customer-db driver.navigate().to(APP_SERVER_BASE_URL + "/customer-portal"); @@ -217,7 +212,7 @@ public class AdapterTestStrategy extends ExternalResource { Client client = ClientBuilder.newClient(); UriBuilder authBase = UriBuilder.fromUri(AUTH_SERVER_URL); WebTarget adminTarget = client.target(AdminRoot.realmsUrl(authBase)).path("demo"); - Map stats = adminTarget.path("application-session-stats").request() + Map stats = adminTarget.path("client-session-stats").request() .header(HttpHeaders.AUTHORIZATION, "Bearer " + adminToken) .get(new GenericType>() { }); @@ -248,7 +243,6 @@ public class AdapterTestStrategy extends ExternalResource { } - @Test public void testServletRequestLogout() throws Exception { // test login to customer-portal which does a bearer request to customer-db driver.navigate().to(APP_SERVER_BASE_URL + "/customer-portal"); @@ -290,7 +284,6 @@ public class AdapterTestStrategy extends ExternalResource { } - @Test public void testLoginSSOIdle() throws Exception { // test login to customer-portal which does a bearer request to customer-db driver.navigate().to(APP_SERVER_BASE_URL + "/customer-portal"); @@ -324,7 +317,6 @@ public class AdapterTestStrategy extends ExternalResource { session.close(); } - @Test public void testLoginSSOIdleRemoveExpiredUserSessions() throws Exception { // test login to customer-portal which does a bearer request to customer-db driver.navigate().to(APP_SERVER_BASE_URL + "/customer-portal"); @@ -366,7 +358,6 @@ public class AdapterTestStrategy extends ExternalResource { session.close(); } - @Test public void testLoginSSOMax() throws Exception { // test login to customer-portal which does a bearer request to customer-db driver.navigate().to(APP_SERVER_BASE_URL + "/customer-portal"); @@ -404,7 +395,6 @@ public class AdapterTestStrategy extends ExternalResource { * KEYCLOAK-518 * @throws Exception */ - @Test public void testNullBearerToken() throws Exception { Client client = ClientBuilder.newClient(); WebTarget target = client.target(APP_SERVER_BASE_URL + "/customer-db/"); @@ -422,7 +412,6 @@ public class AdapterTestStrategy extends ExternalResource { * KEYCLOAK-518 * @throws Exception */ - @Test public void testBadUser() throws Exception { Client client = ClientBuilder.newClient(); UriBuilder builder = UriBuilder.fromUri(AUTH_SERVER_URL); @@ -442,7 +431,6 @@ public class AdapterTestStrategy extends ExternalResource { } - @Test public void testVersion() throws Exception { Client client = ClientBuilder.newClient(); WebTarget target = client.target(AUTH_SERVER_URL).path("version"); @@ -465,7 +453,6 @@ public class AdapterTestStrategy extends ExternalResource { - @Test public void testAuthenticated() throws Exception { // test login to customer-portal which does a bearer request to customer-db driver.navigate().to(APP_SERVER_BASE_URL + "/secure-portal"); @@ -493,7 +480,6 @@ public class AdapterTestStrategy extends ExternalResource { * * @throws Throwable */ - @Test public void testSingleSessionInvalidated() throws Throwable { AdapterTestStrategy browser1 = this; AdapterTestStrategy browser2 = new AdapterTestStrategy(AUTH_SERVER_URL, APP_SERVER_BASE_URL, keycloakRule); @@ -531,7 +517,6 @@ public class AdapterTestStrategy extends ExternalResource { /** * KEYCLOAK-741 */ - @Test public void testSessionInvalidatedAfterFailedRefresh() throws Throwable { final AtomicInteger origTokenLifespan = new AtomicInteger(); @@ -539,7 +524,7 @@ public class AdapterTestStrategy extends ExternalResource { keycloakRule.update(new KeycloakRule.KeycloakSetup() { @Override public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel demoRealm) { - ApplicationModel sessionPortal = demoRealm.getApplicationByName("session-portal"); + ClientModel sessionPortal = demoRealm.getClientByClientId("session-portal"); sessionPortal.setManagementUrl(null); origTokenLifespan.set(demoRealm.getAccessTokenLifespan()); @@ -571,7 +556,7 @@ public class AdapterTestStrategy extends ExternalResource { @Override public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel demoRealm) { - ApplicationModel sessionPortal = demoRealm.getApplicationByName("session-portal"); + ClientModel sessionPortal = demoRealm.getClientByClientId("session-portal"); sessionPortal.setManagementUrl(APP_SERVER_BASE_URL + "/session-portal"); demoRealm.setAccessTokenLifespan(origTokenLifespan.get()); @@ -583,14 +568,13 @@ public class AdapterTestStrategy extends ExternalResource { /** * KEYCLOAK-942 */ - @Test public void testAdminApplicationLogout() throws Throwable { // login as bburke loginAndCheckSession(driver, loginPage); // logout mposolda with admin client - Keycloak keycloakAdmin = Keycloak.getInstance(AUTH_SERVER_URL, "master", "admin", "admin", Constants.ADMIN_CONSOLE_APPLICATION); - keycloakAdmin.realm("demo").applications().get("session-portal").logoutUser("mposolda"); + Keycloak keycloakAdmin = Keycloak.getInstance(AUTH_SERVER_URL, "master", "admin", "admin", Constants.ADMIN_CONSOLE_CLIENT_ID); + keycloakAdmin.realm("demo").clients().get("session-portal").logoutUser("mposolda"); // bburke should be still logged with original httpSession in our browser window driver.navigate().to(APP_SERVER_BASE_URL + "/session-portal"); diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/RelativeUriAdapterTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/RelativeUriAdapterTest.java index 5c6ed7b9e0..4c22533aba 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/RelativeUriAdapterTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/RelativeUriAdapterTest.java @@ -26,7 +26,7 @@ import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; import org.keycloak.OAuth2Constants; -import org.keycloak.models.ApplicationModel; +import org.keycloak.models.ClientModel; import org.keycloak.models.ClientSessionModel; import org.keycloak.models.Constants; import org.keycloak.models.KeycloakSession; @@ -85,7 +85,7 @@ public class RelativeUriAdapterTest { deployApplication("customer-db", "/customer-db", CustomerDatabaseServlet.class, url.getPath(), "user"); url = getClass().getResource("/adapter-test/product-keycloak-relative.json"); deployApplication("product-portal", "/product-portal", ProductServlet.class, url.getPath(), "user"); - ApplicationModel adminConsole = adminRealm.getApplicationByName(Constants.ADMIN_CONSOLE_APPLICATION); + ClientModel adminConsole = adminRealm.getClientByClientId(Constants.ADMIN_CONSOLE_CLIENT_ID); TokenManager tm = new TokenManager(); UserModel admin = session.users().getUserByUsername("admin", adminRealm); ClientSessionModel clientSession = session.sessions().createClientSession(realm, adminConsole); @@ -135,7 +135,7 @@ public class RelativeUriAdapterTest { Client client = ClientBuilder.newClient(); UriBuilder authBase = UriBuilder.fromUri("http://localhost:8081/auth"); WebTarget adminTarget = client.target(AdminRoot.realmsUrl(authBase)).path("demo"); - Map stats = adminTarget.path("application-session-stats").request() + Map stats = adminTarget.path("client-session-stats").request() .header(HttpHeaders.AUTHORIZATION, "Bearer " + adminToken) .get(new GenericType>(){}); diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/AbstractClientTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/AbstractClientTest.java index 4d549095f8..1a8c554eda 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/AbstractClientTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/AbstractClientTest.java @@ -8,9 +8,8 @@ import org.keycloak.admin.client.resource.RealmResource; import org.keycloak.models.Constants; import org.keycloak.models.RealmModel; import org.keycloak.models.utils.KeycloakModelUtils; -import org.keycloak.representations.idm.ApplicationRepresentation; +import org.keycloak.representations.idm.ClientRepresentation; import org.keycloak.representations.idm.IdentityProviderRepresentation; -import org.keycloak.representations.idm.OAuthClientRepresentation; import org.keycloak.representations.idm.RealmRepresentation; import org.keycloak.services.managers.RealmManager; import org.keycloak.testsuite.rule.KeycloakRule; @@ -48,7 +47,7 @@ public abstract class AbstractClientTest { } }); - keycloak = Keycloak.getInstance("http://localhost:8081/auth", "master", "admin", "admin", Constants.ADMIN_CONSOLE_APPLICATION); + keycloak = Keycloak.getInstance("http://localhost:8081/auth", "master", "admin", "admin", Constants.ADMIN_CONSOLE_CLIENT_ID); realm = keycloak.realm(REALM_NAME); } @@ -97,10 +96,8 @@ public abstract class AbstractClientTest { public static String name(Object o1) { if (o1 instanceof RealmRepresentation) { return ((RealmRepresentation) o1).getRealm(); - } else if (o1 instanceof ApplicationRepresentation) { - return ((ApplicationRepresentation) o1).getName(); - } else if (o1 instanceof OAuthClientRepresentation) { - return ((OAuthClientRepresentation) o1).getName(); + } else if (o1 instanceof ClientRepresentation) { + return ((ClientRepresentation) o1).getClientId(); } else if (o1 instanceof IdentityProviderRepresentation) { return ((IdentityProviderRepresentation) o1).getAlias(); } diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/AdminAPITest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/AdminAPITest.java index d72664a210..b3a7ca614e 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/AdminAPITest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/AdminAPITest.java @@ -25,7 +25,7 @@ import org.junit.Assert; import org.junit.ClassRule; import org.junit.Test; import org.keycloak.Config; -import org.keycloak.models.ApplicationModel; +import org.keycloak.models.ClientModel; import org.keycloak.models.ClientSessionModel; import org.keycloak.models.Constants; import org.keycloak.models.KeycloakSession; @@ -35,7 +35,7 @@ import org.keycloak.models.UserSessionModel; import org.keycloak.protocol.oidc.OIDCLoginProtocol; import org.keycloak.protocol.oidc.TokenManager; import org.keycloak.representations.AccessToken; -import org.keycloak.representations.idm.ApplicationRepresentation; +import org.keycloak.representations.idm.ClientRepresentation; import org.keycloak.representations.idm.CredentialRepresentation; import org.keycloak.representations.idm.RealmRepresentation; import org.keycloak.services.managers.RealmManager; @@ -77,7 +77,7 @@ public class AdminAPITest { RealmManager manager = new RealmManager(session); RealmModel adminRealm = manager.getRealm(Config.getAdminRealm()); - ApplicationModel adminConsole = adminRealm.getApplicationByName(Constants.ADMIN_CONSOLE_APPLICATION); + ClientModel adminConsole = adminRealm.getClientByClientId(Constants.ADMIN_CONSOLE_CLIENT_ID); TokenManager tm = new TokenManager(); UserModel admin = session.users().getUserByUsername("admin", adminRealm); ClientSessionModel clientSession = session.sessions().createClientSession(adminRealm, adminConsole); @@ -125,19 +125,19 @@ public class AdminAPITest { storedRealm = realmTarget.request().get(RealmRepresentation.class); checkRealmRep(rep, storedRealm); - if (rep.getApplications() != null) { + if (rep.getClients() != null) { WebTarget applicationsTarget = realmTarget.path("applications"); - for (ApplicationRepresentation appRep : rep.getApplications()) { - ApplicationRepresentation newApp = new ApplicationRepresentation(); + for (ClientRepresentation appRep : rep.getClients()) { + ClientRepresentation newApp = new ClientRepresentation(); if (appRep.getId() != null) newApp.setId(appRep.getId()); - newApp.setName(appRep.getName()); + newApp.setClientId(appRep.getClientId()); if (appRep.getSecret() != null) { newApp.setSecret(appRep.getSecret()); } Response appCreateResponse = applicationsTarget.request().post(Entity.json(newApp)); Assert.assertEquals(201, appCreateResponse.getStatus()); appCreateResponse.close(); - WebTarget appTarget = applicationsTarget.path(appRep.getName()); + WebTarget appTarget = applicationsTarget.path(appRep.getClientId()); CredentialRepresentation cred = appTarget.path("client-secret").request().get(CredentialRepresentation.class); if (appRep.getSecret() != null) Assert.assertEquals(appRep.getSecret(), cred.getValue()); CredentialRepresentation newCred = appTarget.path("client-secret").request().post(null, CredentialRepresentation.class); @@ -148,7 +148,7 @@ public class AdminAPITest { appUpdateResponse.close(); - ApplicationRepresentation storedApp = appTarget.request().get(ApplicationRepresentation.class); + ClientRepresentation storedApp = appTarget.request().get(ClientRepresentation.class); checkAppUpdate(appRep, storedApp); @@ -165,8 +165,8 @@ public class AdminAPITest { client.close(); } - protected void checkAppUpdate(ApplicationRepresentation appRep, ApplicationRepresentation storedApp) { - if (appRep.getName() != null) Assert.assertEquals(appRep.getName(), storedApp.getName()); + protected void checkAppUpdate(ClientRepresentation appRep, ClientRepresentation storedApp) { + if (appRep.getClientId() != null) Assert.assertEquals(appRep.getClientId(), storedApp.getClientId()); if (appRep.isEnabled() != null) Assert.assertEquals(appRep.isEnabled(), storedApp.isEnabled()); if (appRep.isBearerOnly() != null) Assert.assertEquals(appRep.isBearerOnly(), storedApp.isBearerOnly()); if (appRep.isPublicClient() != null) Assert.assertEquals(appRep.isPublicClient(), storedApp.isPublicClient()); diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/ApplicationTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/ClientTest.java similarity index 66% rename from testsuite/integration/src/test/java/org/keycloak/testsuite/admin/ApplicationTest.java rename to testsuite/integration/src/test/java/org/keycloak/testsuite/admin/ClientTest.java index e1902f988b..8151ca5194 100644 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/ApplicationTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/ClientTest.java @@ -2,19 +2,14 @@ package org.keycloak.testsuite.admin; import org.junit.Rule; import org.junit.Test; -import org.keycloak.admin.client.resource.ApplicationResource; +import org.keycloak.admin.client.resource.ClientResource; import org.keycloak.admin.client.resource.ProtocolMappersResource; -import org.keycloak.models.ApplicationModel; -import org.keycloak.models.RealmModel; import org.keycloak.protocol.oidc.OIDCLoginProtocolFactory; -import org.keycloak.representations.idm.ApplicationRepresentation; +import org.keycloak.representations.idm.ClientRepresentation; import org.keycloak.representations.idm.ProtocolMapperRepresentation; -import org.keycloak.representations.idm.RealmRepresentation; import org.keycloak.representations.idm.RoleRepresentation; import org.keycloak.representations.idm.UserSessionRepresentation; -import org.keycloak.services.managers.RealmManager; import org.keycloak.testsuite.OAuthClient; -import org.keycloak.testsuite.rule.KeycloakRule; import org.keycloak.testsuite.rule.WebResource; import org.keycloak.testsuite.rule.WebRule; import org.openqa.selenium.WebDriver; @@ -22,7 +17,6 @@ import org.openqa.selenium.WebDriver; import javax.ws.rs.NotFoundException; import javax.ws.rs.core.Response; -import java.util.LinkedList; import java.util.List; import static org.junit.Assert.assertArrayEquals; @@ -35,7 +29,7 @@ import static org.junit.Assert.fail; /** * @author Stian Thorgersen */ -public class ApplicationTest extends AbstractClientTest { +public class ClientTest extends AbstractClientTest { @Rule public WebRule webRule = new WebRule(this); @@ -47,38 +41,38 @@ public class ApplicationTest extends AbstractClientTest { protected OAuthClient oauth; @Test - public void getApplications() { - assertNames(realm.applications().findAll(), "account", "realm-management", "security-admin-console"); + public void getClients() { + assertNames(realm.clients().findAll(), "account", "realm-management", "security-admin-console"); } @Test - public void createApplication() { - ApplicationRepresentation rep = new ApplicationRepresentation(); - rep.setName("my-app"); + public void createClient() { + ClientRepresentation rep = new ClientRepresentation(); + rep.setClientId("my-app"); rep.setEnabled(true); - realm.applications().create(rep); + realm.clients().create(rep); - assertNames(realm.applications().findAll(), "account", "realm-management", "security-admin-console", "my-app"); + assertNames(realm.clients().findAll(), "account", "realm-management", "security-admin-console", "my-app"); } @Test - public void removeApplication() { - createApplication(); + public void removeClient() { + createClient(); - realm.applications().get("my-app").remove(); + realm.clients().get("my-app").remove(); } @Test - public void getApplicationRepresentation() { - createApplication(); + public void getClientRepresentation() { + createClient(); - ApplicationRepresentation rep = realm.applications().get("my-app").toRepresentation(); - assertEquals("my-app", rep.getName()); + ClientRepresentation rep = realm.clients().get("my-app").toRepresentation(); + assertEquals("my-app", rep.getClientId()); assertTrue(rep.isEnabled()); } @Test - public void getApplicationSessions() throws Exception { + public void getClientSessions() throws Exception { OAuthClient.AccessTokenResponse response = oauth.doGrantAccessTokenRequest("password", "test-user@localhost", "password"); assertEquals(200, response.getStatusCode()); @@ -87,41 +81,41 @@ public class ApplicationTest extends AbstractClientTest { OAuthClient.AccessTokenResponse response2 = oauth.doAccessTokenRequest(codeResponse.getCode(), "password"); assertEquals(200, response2.getStatusCode()); - ApplicationResource app = keycloak.realm("test").applications().get("test-app"); + ClientResource app = keycloak.realm("test").clients().get("test-app"); assertEquals(2, (long) app.getApplicationSessionCount().get("count")); List userSessions = app.getUserSessions(0, 100); assertEquals(2, userSessions.size()); - assertEquals(1, userSessions.get(0).getApplications().size()); + assertEquals(1, userSessions.get(0).getClients().size()); } @Test // KEYCLOAK-1110 public void deleteDefaultRole() { - ApplicationRepresentation rep = new ApplicationRepresentation(); - rep.setName("my-app"); + ClientRepresentation rep = new ClientRepresentation(); + rep.setClientId("my-app"); rep.setEnabled(true); - realm.applications().create(rep); + realm.clients().create(rep); RoleRepresentation role = new RoleRepresentation("test", "test"); - realm.applications().get("my-app").roles().create(role); + realm.clients().get("my-app").roles().create(role); - rep = realm.applications().get("my-app").toRepresentation(); + rep = realm.clients().get("my-app").toRepresentation(); rep.setDefaultRoles(new String[] { "test" }); - realm.applications().get("my-app").update(rep); + realm.clients().get("my-app").update(rep); - assertArrayEquals(new String[] { "test" }, realm.applications().get("my-app").toRepresentation().getDefaultRoles()); + assertArrayEquals(new String[] { "test" }, realm.clients().get("my-app").toRepresentation().getDefaultRoles()); - realm.applications().get("my-app").roles().deleteRole("test"); + realm.clients().get("my-app").roles().deleteRole("test"); - assertNull(realm.applications().get("my-app").toRepresentation().getDefaultRoles()); + assertNull(realm.clients().get("my-app").toRepresentation().getDefaultRoles()); } @Test public void testProtocolMappers() { - createApplication(); - ProtocolMappersResource mappersResource = realm.applications().get("my-app").getProtocolMappers(); + createClient(); + ProtocolMappersResource mappersResource = realm.clients().get("my-app").getProtocolMappers(); protocolMappersTest(mappersResource); } diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/OAuthClientTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/OAuthClientTest.java deleted file mode 100755 index f0641361de..0000000000 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/OAuthClientTest.java +++ /dev/null @@ -1,54 +0,0 @@ -package org.keycloak.testsuite.admin; - -import org.junit.Test; -import org.keycloak.admin.client.resource.ProtocolMappersResource; -import org.keycloak.representations.idm.OAuthClientRepresentation; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -/** - * @author Stian Thorgersen - */ -public class OAuthClientTest extends AbstractClientTest { - - @Test - public void getOAuthClients() { - assertTrue(realm.oAuthClients().findAll().isEmpty()); - } - - @Test - public void createOAuthClient() { - OAuthClientRepresentation rep = new OAuthClientRepresentation(); - rep.setName("my-client"); - rep.setEnabled(true); - realm.oAuthClients().create(rep); - - assertNames(realm.oAuthClients().findAll(), "my-client"); - } - - @Test - public void removeOAuthClient() { - createOAuthClient(); - - realm.oAuthClients().get("my-client").remove(); - } - - @Test - public void testProtocolMappers() { - createOAuthClient(); - ProtocolMappersResource mappersResource = realm.oAuthClients().get("my-client").getProtocolMappers(); - - ApplicationTest.protocolMappersTest(mappersResource); - } - - @Test - public void getOAuthClientRepresentation() { - createOAuthClient(); - - OAuthClientRepresentation rep = realm.oAuthClients().get("my-client").toRepresentation(); - assertEquals("my-client", rep.getName()); - assertTrue(rep.isEnabled()); - } - -} diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/AbstractIdentityProviderTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/AbstractIdentityProviderTest.java index 5e757cc393..9026ebc16d 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/AbstractIdentityProviderTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/AbstractIdentityProviderTest.java @@ -17,6 +17,11 @@ */ package org.keycloak.testsuite.broker; +import org.apache.commons.io.IOUtils; +import org.apache.http.HttpResponse; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.DefaultHttpClient; import org.codehaus.jackson.map.ObjectMapper; import org.junit.After; import org.junit.Before; @@ -24,7 +29,6 @@ import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; import org.keycloak.OAuth2Constants; -import org.keycloak.models.ApplicationModel; import org.keycloak.models.ClientIdentityProviderMappingModel; import org.keycloak.models.ClientModel; import org.keycloak.models.FederatedIdentityModel; @@ -45,7 +49,6 @@ import org.keycloak.testsuite.pages.LoginUpdateProfilePage; import org.keycloak.testsuite.pages.OAuthGrantPage; import org.keycloak.testsuite.rule.WebResource; import org.keycloak.testsuite.rule.WebRule; -import org.keycloak.testsuite.rule.WebRule.HtmlUnitDriver; import org.openqa.selenium.By; import org.openqa.selenium.NoSuchElementException; import org.openqa.selenium.WebDriver; @@ -60,18 +63,17 @@ import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; import javax.ws.rs.core.UriBuilder; - import java.io.IOException; import java.net.URI; import java.util.ArrayList; import java.util.List; import java.util.Set; -import static com.thoughtworks.selenium.SeleneseTestBase.fail; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; /** * @author pedroigor @@ -278,10 +280,10 @@ public abstract class AbstractIdentityProviderTest { public void testProviderOnLoginPage() { IdentityProviderModel identityProviderModel = getIdentityProviderModel(); RealmModel realm = getRealm(); - ApplicationModel applicationModel = realm.getApplicationByName("test-app"); + ClientModel clientModel = realm.getClientByClientId("test-app"); // This client doesn't have any specific identity providers settings - ClientModel client2 = realm.findClient("test-app"); + ClientModel client2 = realm.getClientByClientId("test-app"); assertEquals(0, client2.getIdentityProviders().size()); // Provider button is available on login page @@ -295,7 +297,7 @@ public abstract class AbstractIdentityProviderTest { mapping.setIdentityProvider(getProviderId()); mapping.setRetrieveToken(true); appIdentityProviders.add(mapping); - applicationModel.updateIdentityProviders(appIdentityProviders); + clientModel.updateIdentityProviders(appIdentityProviders); // Provider button still available on login page this.driver.navigate().to("http://localhost:8081/test-app/"); @@ -437,7 +439,7 @@ public abstract class AbstractIdentityProviderTest { assertNotNull(identityModel.getToken()); - configureRetrieveToken(realm.findClient("test-app"), getProviderId(), false); + configureRetrieveToken(realm.getClientByClientId("test-app"), getProviderId(), false); UserSessionStatus userSessionStatus = retrieveSessionStatus(); String accessToken = userSessionStatus.getAccessTokenString(); @@ -455,7 +457,7 @@ public abstract class AbstractIdentityProviderTest { assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus()); - configureRetrieveToken(getRealm().findClient("test-app"), getProviderId(), true); + configureRetrieveToken(getRealm().getClientByClientId("test-app"), getProviderId(), true); client = ClientBuilder.newBuilder().register(authFilter).build(); tokenEndpoint = client.target(tokenEndpointUrl); @@ -505,26 +507,30 @@ public abstract class AbstractIdentityProviderTest { assertTrue(oauth.getCurrentQuery().containsKey(OAuth2Constants.CODE)); - ClientModel clientModel = getRealm().findClient("third-party"); + ClientModel clientModel = getRealm().getClientByClientId("third-party"); assertEquals(0, clientModel.getIdentityProviders().size()); configureRetrieveToken(clientModel, getProviderId(), true); AccessTokenResponse accessToken = oauth.doAccessTokenRequest(oauth.getCurrentQuery().get(OAuth2Constants.CODE), "password"); - URI tokenEndpointUrl = Urls.identityProviderRetrieveToken(BASE_URI, getProviderId(), getRealm().getName()); - String authHeader = "Bearer " + accessToken.getAccessToken(); - HtmlUnitDriver htmlUnitDriver = (WebRule.HtmlUnitDriver) this.driver; - htmlUnitDriver.getWebClient().addRequestHeader(HttpHeaders.AUTHORIZATION, authHeader); + doTokenRequest(accessToken.getAccessToken()); + } - htmlUnitDriver.navigate().to(tokenEndpointUrl.toString()); + public void doTokenRequest(String token) { + try { + HttpClient client = new DefaultHttpClient(); + HttpGet get = new HttpGet(Urls.identityProviderRetrieveToken(BASE_URI, getProviderId(), getRealm().getName())); - grantPage.assertCurrent(); - grantPage.accept(); + get.setHeader("Authorization", "Bearer " + token); - assertNotNull(driver.getPageSource()); + HttpResponse response = client.execute(get); + assertEquals(200, response.getStatusLine().getStatusCode()); - doAssertTokenRetrieval(driver.getPageSource()); + assertNotNull(IOUtils.toString(response.getEntity().getContent())); + } catch (Exception e) { + fail(e.getMessage()); + } } private void configureRetrieveToken(ClientModel clientModel, String providerId, boolean retrieveToken) { diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/ImportIdentityProviderTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/ImportIdentityProviderTest.java index eda8b6902c..a1f824511a 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/ImportIdentityProviderTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/ImportIdentityProviderTest.java @@ -30,8 +30,8 @@ import org.keycloak.broker.oidc.OIDCIdentityProviderFactory; import org.keycloak.broker.saml.SAMLIdentityProvider; import org.keycloak.broker.saml.SAMLIdentityProviderConfig; import org.keycloak.broker.saml.SAMLIdentityProviderFactory; -import org.keycloak.models.ClientIdentityProviderMappingModel; import org.keycloak.models.ClientModel; +import org.keycloak.models.ClientIdentityProviderMappingModel; import org.keycloak.models.IdentityProviderModel; import org.keycloak.models.RealmModel; import org.keycloak.representations.idm.RealmRepresentation; @@ -122,7 +122,7 @@ public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTes public void testApplicationIdentityProviders() throws Exception { RealmModel realm = installTestRealm(); - ClientModel client = realm.findClient("test-app-with-allowed-providers"); + ClientModel client = realm.getClientByClientId("test-app-with-allowed-providers"); List identityProviders = client.getIdentityProviders(); assertEquals(1, identityProviders.size()); @@ -136,7 +136,7 @@ public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTes client.updateIdentityProviders(identityProviders); - client = realm.findClientById(client.getId()); + client = realm.getClientById(client.getId()); identityProviders = client.getIdentityProviders(); assertEquals(0, identityProviders.size()); diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/composites/CompositeRoleTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/composites/CompositeRoleTest.java index b661d5a08b..7178f1de10 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/composites/CompositeRoleTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/composites/CompositeRoleTest.java @@ -27,7 +27,7 @@ import org.junit.Rule; import org.junit.Test; import org.keycloak.OAuth2Constants; import org.keycloak.enums.SslRequired; -import org.keycloak.models.ApplicationModel; +import org.keycloak.models.ClientModel; import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; import org.keycloak.models.RoleModel; @@ -35,7 +35,7 @@ import org.keycloak.models.UserCredentialModel; import org.keycloak.models.UserModel; import org.keycloak.models.utils.KeycloakModelUtils; import org.keycloak.representations.AccessToken; -import org.keycloak.services.managers.ApplicationManager; +import org.keycloak.services.managers.ClientManager; import org.keycloak.services.managers.RealmManager; import org.keycloak.testsuite.ApplicationServlet; import org.keycloak.testsuite.OAuthClient; @@ -85,7 +85,7 @@ public class CompositeRoleTest { realmRole1User.updateCredential(UserCredentialModel.password("password")); realmRole1User.grantRole(realmRole1); - final ApplicationModel realmComposite1Application = new ApplicationManager(manager).createApplication(realm, "REALM_COMPOSITE_1_APPLICATION"); + final ClientModel realmComposite1Application = new ClientManager(manager).createClient(realm, "REALM_COMPOSITE_1_APPLICATION"); realmComposite1Application.setFullScopeAllowed(false); realmComposite1Application.setEnabled(true); realmComposite1Application.addScopeMapping(realmComposite1); @@ -94,7 +94,7 @@ public class CompositeRoleTest { realmComposite1Application.setManagementUrl("http://localhost:8081/app/logout"); realmComposite1Application.setSecret("password"); - final ApplicationModel realmRole1Application = new ApplicationManager(manager).createApplication(realm, "REALM_ROLE_1_APPLICATION"); + final ClientModel realmRole1Application = new ClientManager(manager).createClient(realm, "REALM_ROLE_1_APPLICATION"); realmRole1Application.setFullScopeAllowed(false); realmRole1Application.setEnabled(true); realmRole1Application.addScopeMapping(realmRole1); @@ -104,7 +104,7 @@ public class CompositeRoleTest { realmRole1Application.setSecret("password"); - final ApplicationModel appRoleApplication = new ApplicationManager(manager).createApplication(realm, "APP_ROLE_APPLICATION"); + final ClientModel appRoleApplication = new ClientManager(manager).createClient(realm, "APP_ROLE_APPLICATION"); appRoleApplication.setFullScopeAllowed(false); appRoleApplication.setEnabled(true); appRoleApplication.addRedirectUri("http://localhost:8081/app/*"); @@ -127,7 +127,7 @@ public class CompositeRoleTest { realmAppRoleUser.updateCredential(UserCredentialModel.password("password")); realmAppRoleUser.grantRole(appRole2); - final ApplicationModel appCompositeApplication = new ApplicationManager(manager).createApplication(realm, "APP_COMPOSITE_APPLICATION"); + final ClientModel appCompositeApplication = new ClientManager(manager).createClient(realm, "APP_COMPOSITE_APPLICATION"); appCompositeApplication.setFullScopeAllowed(false); appCompositeApplication.setEnabled(true); appCompositeApplication.addRedirectUri("http://localhost:8081/app/*"); diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/AbstractKerberosTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/AbstractKerberosTest.java index af994f4a0e..25802429e8 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/AbstractKerberosTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/AbstractKerberosTest.java @@ -21,7 +21,7 @@ import org.keycloak.adapters.HttpClientBuilder; import org.keycloak.events.Details; import org.keycloak.federation.kerberos.CommonKerberosConfig; import org.keycloak.constants.KerberosConstants; -import org.keycloak.models.ApplicationModel; +import org.keycloak.models.ClientModel; import org.keycloak.models.KeycloakSession; import org.keycloak.models.LDAPConstants; import org.keycloak.models.ProtocolMapperModel; @@ -183,7 +183,7 @@ public abstract class AbstractKerberosTest { true, KerberosConstants.GSS_DELEGATION_CREDENTIAL_DISPLAY_NAME, true, false); - ApplicationModel kerberosApp = appRealm.getApplicationByName("kerberos-app"); + ClientModel kerberosApp = appRealm.getClientByClientId("kerberos-app"); kerberosApp.addProtocolMapper(protocolMapper); } @@ -202,7 +202,7 @@ public abstract class AbstractKerberosTest { @Override public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) { - ApplicationModel kerberosApp = appRealm.getApplicationByName("kerberos-app"); + ClientModel kerberosApp = appRealm.getClientByClientId("kerberos-app"); ProtocolMapperModel toRemove = kerberosApp.getProtocolMapperByName(OIDCLoginProtocol.LOGIN_PROTOCOL, KerberosConstants.GSS_DELEGATION_CREDENTIAL_DISPLAY_NAME); kerberosApp.removeProtocolMapper(toRemove); } diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/FederationProvidersIntegrationTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/FederationProvidersIntegrationTest.java index cfaae07ec8..929029eef5 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/FederationProvidersIntegrationTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/FederationProvidersIntegrationTest.java @@ -12,6 +12,8 @@ import org.keycloak.OAuth2Constants; import org.keycloak.federation.ldap.LDAPFederationProvider; import org.keycloak.federation.ldap.LDAPFederationProviderFactory; import org.keycloak.federation.ldap.LDAPUtils; +import org.keycloak.federation.ldap.idm.model.LDAPUser; +import org.keycloak.federation.ldap.idm.store.ldap.LDAPIdentityStore; import org.keycloak.models.KeycloakSession; import org.keycloak.models.LDAPConstants; import org.keycloak.models.ModelReadOnlyException; @@ -21,7 +23,6 @@ import org.keycloak.models.UserCredentialValueModel; import org.keycloak.models.UserFederationProvider; import org.keycloak.models.UserFederationProviderModel; import org.keycloak.models.UserModel; -import org.keycloak.picketlink.PartitionManagerProvider; import org.keycloak.representations.idm.CredentialRepresentation; import org.keycloak.services.managers.RealmManager; import org.keycloak.testsuite.OAuthClient; @@ -35,8 +36,6 @@ import org.keycloak.testsuite.rule.LDAPRule; import org.keycloak.testsuite.rule.WebResource; import org.keycloak.testsuite.rule.WebRule; import org.openqa.selenium.WebDriver; -import org.picketlink.idm.PartitionManager; -import org.picketlink.idm.model.basic.User; import java.util.Map; @@ -57,19 +56,19 @@ public class FederationProvidersIntegrationTest { addUser(manager.getSession(), appRealm, "mary", "mary@test.com", "password-app"); Map ldapConfig = ldapRule.getConfig(); - ldapConfig.put(LDAPFederationProvider.SYNC_REGISTRATIONS, "true"); + ldapConfig.put(LDAPConstants.SYNC_REGISTRATIONS, "true"); ldapConfig.put(LDAPConstants.EDIT_MODE, UserFederationProvider.EditMode.WRITABLE.toString()); ldapModel = appRealm.addUserFederationProvider(LDAPFederationProviderFactory.PROVIDER_NAME, ldapConfig, 0, "test-ldap", -1, -1, 0); // Delete all LDAP users and add some new for testing - PartitionManager partitionManager = getPartitionManager(manager.getSession(), ldapModel); - LDAPUtils.removeAllUsers(partitionManager); + LDAPIdentityStore ldapStore = getLdapIdentityStore(manager.getSession(), ldapModel); + LDAPUtils.removeAllUsers(ldapStore); - User john = LDAPUtils.addUser(partitionManager, "johnkeycloak", "John", "Doe", "john@email.org"); - LDAPUtils.updatePassword(partitionManager, john, "Password1"); + LDAPUser john = LDAPUtils.addUser(ldapStore, "johnkeycloak", "John", "Doe", "john@email.org"); + LDAPUtils.updatePassword(ldapStore, john, "Password1"); - User existing = LDAPUtils.addUser(partitionManager, "existing", "Existing", "Foo", "existing@email.org"); + LDAPUser existing = LDAPUtils.addUser(ldapStore, "existing", "Existing", "Foo", "existing@email.org"); } }); @@ -339,13 +338,13 @@ public class FederationProvidersIntegrationTest { @Test public void testSearch() { KeycloakSession session = keycloakRule.startSession(); - PartitionManager partitionManager = getPartitionManager(session, ldapModel); + LDAPIdentityStore ldapStore = getLdapIdentityStore(session, ldapModel); try { RealmModel appRealm = session.realms().getRealmByName("test"); - LDAPUtils.addUser(partitionManager, "username1", "John1", "Doel1", "user1@email.org"); - LDAPUtils.addUser(partitionManager, "username2", "John2", "Doel2", "user2@email.org"); - LDAPUtils.addUser(partitionManager, "username3", "John3", "Doel3", "user3@email.org"); - LDAPUtils.addUser(partitionManager, "username4", "John4", "Doel4", "user4@email.org"); + LDAPUtils.addUser(ldapStore, "username1", "John1", "Doel1", "user1@email.org"); + LDAPUtils.addUser(ldapStore, "username2", "John2", "Doel2", "user2@email.org"); + LDAPUtils.addUser(ldapStore, "username3", "John3", "Doel3", "user3@email.org"); + LDAPUtils.addUser(ldapStore, "username4", "John4", "Doel4", "user4@email.org"); // Users are not at local store at this moment Assert.assertNull(session.userStorage().getUserByUsername("username1", appRealm)); @@ -395,7 +394,7 @@ public class FederationProvidersIntegrationTest { Assert.assertTrue(session.users().validCredentials(appRealm, user, cred)); // LDAP password is still unchanged - Assert.assertTrue(LDAPUtils.validatePassword(getPartitionManager(session, model), "johnkeycloak", "Password1")); + Assert.assertTrue(LDAPUtils.validatePassword(getLdapIdentityStore(session, model), user, "Password1")); // ATM it's not permitted to delete user in unsynced mode. Should be user deleted just locally instead? Assert.assertFalse(session.users().removeUser(appRealm, user)); @@ -412,9 +411,10 @@ public class FederationProvidersIntegrationTest { } } - static PartitionManager getPartitionManager(KeycloakSession keycloakSession, UserFederationProviderModel ldapFedModel) { - PartitionManagerProvider partitionManagerProvider = keycloakSession.getProvider(PartitionManagerProvider.class); - return partitionManagerProvider.getPartitionManager(ldapFedModel); + static LDAPIdentityStore getLdapIdentityStore(KeycloakSession keycloakSession, UserFederationProviderModel ldapFedModel) { + LDAPFederationProviderFactory ldapProviderFactory = (LDAPFederationProviderFactory) keycloakSession.getKeycloakSessionFactory().getProviderFactory(UserFederationProvider.class, ldapFedModel.getProviderName()); + LDAPFederationProvider ldapProvider = ldapProviderFactory.getInstance(keycloakSession, ldapFedModel); + return ldapProvider.getLdapIdentityStore(); } } diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/SyncProvidersTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/SyncProvidersTest.java index 55f68bb656..f628519af7 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/SyncProvidersTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/SyncProvidersTest.java @@ -7,9 +7,10 @@ import org.junit.Test; import org.junit.rules.RuleChain; import org.junit.rules.TestRule; import org.junit.runners.MethodSorters; -import org.keycloak.federation.ldap.LDAPFederationProvider; import org.keycloak.federation.ldap.LDAPFederationProviderFactory; import org.keycloak.federation.ldap.LDAPUtils; +import org.keycloak.federation.ldap.idm.model.LDAPUser; +import org.keycloak.federation.ldap.idm.store.ldap.LDAPIdentityStore; import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSessionFactory; import org.keycloak.models.LDAPConstants; @@ -25,8 +26,6 @@ import org.keycloak.testsuite.rule.LDAPRule; import org.keycloak.testutils.DummyUserFederationProviderFactory; import org.keycloak.timer.TimerProvider; import org.keycloak.util.Time; -import org.picketlink.idm.PartitionManager; -import org.picketlink.idm.model.basic.User; import java.util.HashMap; import java.util.Map; @@ -50,26 +49,20 @@ public class SyncProvidersTest { Time.setOffset(0); Map ldapConfig = ldapRule.getConfig(); - ldapConfig.put(LDAPFederationProvider.SYNC_REGISTRATIONS, "false"); + ldapConfig.put(LDAPConstants.SYNC_REGISTRATIONS, "false"); ldapConfig.put(LDAPConstants.EDIT_MODE, UserFederationProvider.EditMode.UNSYNCED.toString()); ldapModel = appRealm.addUserFederationProvider(LDAPFederationProviderFactory.PROVIDER_NAME, ldapConfig, 0, "test-ldap", -1, -1, 0); // Delete all LDAP users and add 5 new users for testing - PartitionManager partitionManager = FederationProvidersIntegrationTest.getPartitionManager(manager.getSession(), ldapModel); - LDAPUtils.removeAllUsers(partitionManager); + LDAPIdentityStore ldapStore = FederationProvidersIntegrationTest.getLdapIdentityStore(manager.getSession(), ldapModel); + LDAPUtils.removeAllUsers(ldapStore); - User user1 = LDAPUtils.addUser(partitionManager, "user1", "User1FN", "User1LN", "user1@email.org"); - LDAPUtils.updatePassword(partitionManager, user1, "Password1"); - User user2 = LDAPUtils.addUser(partitionManager, "user2", "User2FN", "User2LN", "user2@email.org"); - LDAPUtils.updatePassword(partitionManager, user2, "Password2"); - User user3 = LDAPUtils.addUser(partitionManager, "user3", "User3FN", "User3LN", "user3@email.org"); - LDAPUtils.updatePassword(partitionManager, user3, "Password3"); - User user4 = LDAPUtils.addUser(partitionManager, "user4", "User4FN", "User4LN", "user4@email.org"); - LDAPUtils.updatePassword(partitionManager, user4, "Password4"); - User user5 = LDAPUtils.addUser(partitionManager, "user5", "User5FN", "User5LN", "user5@email.org"); - LDAPUtils.updatePassword(partitionManager, user5, "Password5"); + for (int i=1 ; i<6 ; i++) { + LDAPUser user = LDAPUtils.addUser(ldapStore, "user" + i, "User" + i + "FN", "User" + i + "LN", "user" + i + "@email.org"); + LDAPUtils.updatePassword(ldapStore, user, "Password1"); + } // Add dummy provider dummyModel = appRealm.addUserFederationProvider(DummyUserFederationProviderFactory.PROVIDER_NAME, new HashMap(), 1, "test-dummy", -1, 1, 0); @@ -122,9 +115,9 @@ public class SyncProvidersTest { sleep(1000); // Add user to LDAP and update 'user5' in LDAP - PartitionManager partitionManager = FederationProvidersIntegrationTest.getPartitionManager(session, ldapModel); - LDAPUtils.addUser(partitionManager, "user6", "User6FN", "User6LN", "user6@email.org"); - LDAPUtils.updateUser(partitionManager, "user5", "User5FNUpdated", "User5LNUpdated", "user5Updated@email.org"); + LDAPIdentityStore ldapStore = FederationProvidersIntegrationTest.getLdapIdentityStore(session, ldapModel); + LDAPUtils.addUser(ldapStore, "user6", "User6FN", "User6LN", "user6@email.org"); + LDAPUtils.updateUser(ldapStore, "user5", "User5FNUpdated", "User5LNUpdated", "user5Updated@email.org"); // Assert still old users in local provider assertUserImported(userProvider, testRealm, "user5", "User5FN", "User5LN", "user5@email.org"); diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/jaxrs/JaxrsBasicAuthTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/jaxrs/JaxrsBasicAuthTest.java index 252a253761..1b5a249e91 100644 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/jaxrs/JaxrsBasicAuthTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/jaxrs/JaxrsBasicAuthTest.java @@ -19,10 +19,8 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExternalResource; import org.keycloak.adapters.HttpClientBuilder; -import org.keycloak.models.ApplicationModel; +import org.keycloak.models.ClientModel; import org.keycloak.models.RealmModel; -import org.keycloak.models.RoleModel; -import org.keycloak.models.UserModel; import org.keycloak.services.managers.RealmManager; import org.keycloak.testsuite.Constants; import org.keycloak.testsuite.rule.KeycloakRule; @@ -44,7 +42,7 @@ public class JaxrsBasicAuthTest { @Override public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) { - ApplicationModel app = appRealm.addApplication("jaxrs-app"); + ClientModel app = appRealm.addClient("jaxrs-app"); app.setEnabled(true); app.setSecret("password"); app.setFullScopeAllowed(true); diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/jaxrs/JaxrsFilterTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/jaxrs/JaxrsFilterTest.java index 2ff046c0d2..5d597351e2 100644 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/jaxrs/JaxrsFilterTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/jaxrs/JaxrsFilterTest.java @@ -23,7 +23,7 @@ import org.keycloak.TokenIdGenerator; import org.keycloak.adapters.CorsHeaders; import org.keycloak.constants.AdapterConstants; import org.keycloak.adapters.HttpClientBuilder; -import org.keycloak.models.ApplicationModel; +import org.keycloak.models.ClientModel; import org.keycloak.models.RealmModel; import org.keycloak.models.RoleModel; import org.keycloak.models.UserModel; @@ -53,7 +53,7 @@ public class JaxrsFilterTest { @Override public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) { - ApplicationModel app = appRealm.addApplication("jaxrs-app"); + ClientModel app = appRealm.addClient("jaxrs-app"); app.setEnabled(true); RoleModel role = app.addRole("jaxrs-app-user"); UserModel user = manager.getSession().users().getUserByUsername("test-user@localhost", appRealm); diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/AdapterTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/AdapterTest.java index a2ebb91f5d..0e48914430 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/AdapterTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/AdapterTest.java @@ -4,10 +4,9 @@ import org.junit.Assert; import org.junit.FixMethodOrder; import org.junit.Test; import org.junit.runners.MethodSorters; -import org.keycloak.models.ApplicationModel; +import org.keycloak.models.ClientModel; import org.keycloak.models.FederatedIdentityModel; import org.keycloak.models.ModelDuplicateException; -import org.keycloak.models.OAuthClientModel; import org.keycloak.models.PasswordPolicy; import org.keycloak.models.RealmModel; import org.keycloak.models.RequiredCredentialModel; @@ -16,7 +15,6 @@ import org.keycloak.models.UserCredentialModel; import org.keycloak.models.UserCredentialValueModel; import org.keycloak.models.UserModel; import org.keycloak.models.UserProvider; -import org.keycloak.models.utils.RepresentationToModel; import org.keycloak.representations.idm.CredentialRepresentation; import org.keycloak.services.managers.RealmManager; @@ -152,15 +150,6 @@ public class AdapterTest extends AbstractModelTest { realmModel.setPasswordPolicy( new PasswordPolicy("hashIterations(1)")); } - @Test - public void testOAuthClient() throws Exception { - test1CreateRealm(); - - RepresentationToModel.createOAuthClient(null, "oauth-client", realmModel); - OAuthClientModel oauth = realmModel.getOAuthClient("oauth-client"); - Assert.assertNotNull(oauth); - } - @Test public void testDeleteUser() throws Exception { test1CreateRealm(); @@ -172,7 +161,7 @@ public class AdapterTest extends AbstractModelTest { RoleModel testRole = realmModel.addRole("test"); user.grantRole(testRole); - ApplicationModel app = realmModel.addApplication("test-app"); + ClientModel app = realmModel.addClient("test-app"); RoleModel appRole = app.addRole("test"); user.grantRole(appRole); @@ -197,9 +186,9 @@ public class AdapterTest extends AbstractModelTest { UserModel user = realmManager.getSession().users().addUser(realmModel, "bburke"); - OAuthClientModel client = realmModel.addOAuthClient("client"); + ClientModel client = realmModel.addClient("client"); - ApplicationModel app = realmModel.addApplication("test-app"); + ClientModel app = realmModel.addClient("test-app"); RoleModel appRole = app.addRole("test"); user.grantRole(appRole); @@ -208,9 +197,9 @@ public class AdapterTest extends AbstractModelTest { RoleModel realmRole = realmModel.addRole("test"); app.addScopeMapping(realmRole); - Assert.assertTrue(realmModel.removeApplication(app.getId())); - Assert.assertFalse(realmModel.removeApplication(app.getId())); - assertNull(realmModel.getApplicationById(app.getId())); + Assert.assertTrue(realmModel.removeClient(app.getId())); + Assert.assertFalse(realmModel.removeClient(app.getId())); + assertNull(realmModel.getClientById(app.getId())); } @@ -225,9 +214,9 @@ public class AdapterTest extends AbstractModelTest { cred.setValue("password"); user.updateCredential(cred); - OAuthClientModel client = realmModel.addOAuthClient("client"); + ClientModel client = realmModel.addClient("client"); - ApplicationModel app = realmModel.addApplication("test-app"); + ClientModel app = realmModel.addClient("test-app"); RoleModel appRole = app.addRole("test"); user.grantRole(appRole); @@ -255,9 +244,9 @@ public class AdapterTest extends AbstractModelTest { UserModel user = realmManager.getSession().users().addUser(realmModel, "bburke"); - OAuthClientModel client = realmModel.addOAuthClient("client"); + ClientModel client = realmModel.addClient("client"); - ApplicationModel app = realmModel.addApplication("test-app"); + ClientModel app = realmModel.addClient("test-app"); RoleModel appRole = app.addRole("test"); user.grantRole(appRole); @@ -268,7 +257,7 @@ public class AdapterTest extends AbstractModelTest { commit(); realmModel = model.getRealm("JUGGLER"); - app = realmModel.getApplicationByName("test-app"); + app = realmModel.getClientByClientId("test-app"); Assert.assertTrue(realmModel.removeRoleById(realmRole.getId())); Assert.assertFalse(realmModel.removeRoleById(realmRole.getId())); @@ -458,7 +447,7 @@ public class AdapterTest extends AbstractModelTest { assertRolesEquals(found, realmUserRole); // Test app roles - ApplicationModel application = realmModel.addApplication("app1"); + ClientModel application = realmModel.addClient("app1"); application.addRole("user"); application.addRole("bar"); Set appRoles = application.getRoles(); @@ -480,7 +469,7 @@ public class AdapterTest extends AbstractModelTest { // Role "foo" is default realm role Assert.assertTrue(user.hasRole(realmModel.getRole("foo"))); - roles = user.getApplicationRoleMappings(application); + roles = user.getClientRoleMappings(application); Assert.assertEquals(roles.size(), 2); assertRolesContains(application.getRole("user"), roles); assertRolesContains(appBarRole, roles); @@ -506,23 +495,23 @@ public class AdapterTest extends AbstractModelTest { test1CreateRealm(); RoleModel realmRole = realmModel.addRole("realm"); - ApplicationModel app1 = realmModel.addApplication("app1"); + ClientModel app1 = realmModel.addClient("app1"); RoleModel appRole = app1.addRole("app"); - ApplicationModel app2 = realmModel.addApplication("app2"); + ClientModel app2 = realmModel.addClient("app2"); app2.addScopeMapping(realmRole); app2.addScopeMapping(appRole); - OAuthClientModel client = realmModel.addOAuthClient("client"); + ClientModel client = realmModel.addClient("client"); client.addScopeMapping(realmRole); client.addScopeMapping(appRole); commit(); realmModel = model.getRealmByName("JUGGLER"); - app1 = realmModel.getApplicationByName("app1"); - app2 = realmModel.getApplicationByName("app2"); - client = realmModel.getOAuthClient("client"); + app1 = realmModel.getClientByClientId("app1"); + app2 = realmModel.getClientByClientId("app2"); + client = realmModel.getClientByClientId("client"); Set scopeMappings = app2.getScopeMappings(); Assert.assertEquals(2, scopeMappings.size()); @@ -565,14 +554,14 @@ public class AdapterTest extends AbstractModelTest { @Test public void testAppNameCollisions() throws Exception { - realmManager.createRealm("JUGGLER1").addApplication("app1"); - realmManager.createRealm("JUGGLER2").addApplication("app1"); + realmManager.createRealm("JUGGLER1").addClient("app1"); + realmManager.createRealm("JUGGLER2").addClient("app1"); commit(); // Try to create app with duplicate name try { - realmManager.getRealmByName("JUGGLER1").addApplication("app1"); + realmManager.getRealmByName("JUGGLER1").addClient("app1"); commit(); Assert.fail("Expected exception"); } catch (ModelDuplicateException e) { @@ -580,10 +569,10 @@ public class AdapterTest extends AbstractModelTest { commit(true); // Ty to rename app to duplicate name - realmManager.getRealmByName("JUGGLER1").addApplication("app2"); + realmManager.getRealmByName("JUGGLER1").addClient("app2"); commit(); try { - realmManager.getRealmByName("JUGGLER1").getApplicationByName("app2").setName("app1"); + realmManager.getRealmByName("JUGGLER1").getClientByClientId("app2").setClientId("app1"); commit(); Assert.fail("Expected exception"); } catch (ModelDuplicateException e) { @@ -594,14 +583,14 @@ public class AdapterTest extends AbstractModelTest { @Test public void testClientNameCollisions() throws Exception { - realmManager.createRealm("JUGGLER1").addOAuthClient("client1"); - realmManager.createRealm("JUGGLER2").addOAuthClient("client1"); + realmManager.createRealm("JUGGLER1").addClient("client1"); + realmManager.createRealm("JUGGLER2").addClient("client1"); commit(); // Try to create app with duplicate name try { - realmManager.getRealmByName("JUGGLER1").addOAuthClient("client1"); + realmManager.getRealmByName("JUGGLER1").addClient("client1"); commit(); Assert.fail("Expected exception"); } catch (ModelDuplicateException e) { @@ -609,10 +598,10 @@ public class AdapterTest extends AbstractModelTest { commit(true); // Ty to rename app to duplicate name - realmManager.getRealmByName("JUGGLER1").addOAuthClient("client2"); + realmManager.getRealmByName("JUGGLER1").addClient("client2"); commit(); try { - realmManager.getRealmByName("JUGGLER1").getOAuthClient("client2").setClientId("client1"); + realmManager.getRealmByName("JUGGLER1").addClient("client2").setClientId("client1"); commit(); Assert.fail("Expected exception"); } catch (ModelDuplicateException e) { @@ -691,14 +680,14 @@ public class AdapterTest extends AbstractModelTest { @Test public void testAppRoleCollisions() throws Exception { realmManager.createRealm("JUGGLER1").addRole("role1"); - realmManager.getRealmByName("JUGGLER1").addApplication("app1").addRole("role1"); - realmManager.getRealmByName("JUGGLER1").addApplication("app2").addRole("role1"); + realmManager.getRealmByName("JUGGLER1").addClient("app1").addRole("role1"); + realmManager.getRealmByName("JUGGLER1").addClient("app2").addRole("role1"); commit(); // Try to add role with same name try { - realmManager.getRealmByName("JUGGLER1").getApplicationByName("app1").addRole("role1"); + realmManager.getRealmByName("JUGGLER1").getClientByClientId("app1").addRole("role1"); commit(); Assert.fail("Expected exception"); } catch (ModelDuplicateException e) { @@ -706,10 +695,10 @@ public class AdapterTest extends AbstractModelTest { commit(true); // Ty to rename role to duplicate name - realmManager.getRealmByName("JUGGLER1").getApplicationByName("app1").addRole("role2"); + realmManager.getRealmByName("JUGGLER1").getClientByClientId("app1").addRole("role2"); commit(); try { - realmManager.getRealmByName("JUGGLER1").getApplicationByName("app1").getRole("role2").setName("role1"); + realmManager.getRealmByName("JUGGLER1").getClientByClientId("app1").getRole("role2").setName("role1"); commit(); Assert.fail("Expected exception"); } catch (ModelDuplicateException e) { @@ -721,8 +710,8 @@ public class AdapterTest extends AbstractModelTest { @Test public void testRealmRoleCollisions() throws Exception { realmManager.createRealm("JUGGLER1").addRole("role1"); - realmManager.getRealmByName("JUGGLER1").addApplication("app1").addRole("role1"); - realmManager.getRealmByName("JUGGLER1").addApplication("app2").addRole("role1"); + realmManager.getRealmByName("JUGGLER1").addClient("app1").addRole("role1"); + realmManager.getRealmByName("JUGGLER1").addClient("app2").addRole("role1"); commit(); diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ApplicationModelTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ApplicationModelTest.java deleted file mode 100755 index e55a325cee..0000000000 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ApplicationModelTest.java +++ /dev/null @@ -1,103 +0,0 @@ -package org.keycloak.testsuite.model; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.keycloak.models.ApplicationModel; -import org.keycloak.models.RealmModel; -import org.keycloak.models.RoleModel; -import org.keycloak.models.utils.ModelToRepresentation; -import org.keycloak.models.utils.RepresentationToModel; -import org.keycloak.representations.idm.ApplicationRepresentation; -import org.keycloak.services.managers.ApplicationManager; - -import java.util.Iterator; -import java.util.List; - -/** - * @author Stian Thorgersen - */ -public class ApplicationModelTest extends AbstractModelTest { - private ApplicationModel application; - private RealmModel realm; - private ApplicationManager appManager; - - @Before - @Override - public void before() throws Exception { - super.before(); - appManager = new ApplicationManager(realmManager); - - realm = realmManager.createRealm("original"); - application = realm.addApplication("application"); - application.setBaseUrl("http://base"); - application.setManagementUrl("http://management"); - application.setName("app-name"); - application.addRole("role-1"); - application.addRole("role-2"); - application.addRole("role-3"); - application.addDefaultRole("role-1"); - application.addDefaultRole("role-2"); - - application.addRedirectUri("redirect-1"); - application.addRedirectUri("redirect-2"); - - application.addWebOrigin("origin-1"); - application.addWebOrigin("origin-2"); - - application.registerNode("node1", 10); - application.registerNode("10.20.30.40", 50); - - application.updateApplication(); - } - - @Test - public void persist() { - RealmModel persisted = realmManager.getRealm(realm.getId()); - - ApplicationModel actual = persisted.getApplicationNameMap().get("app-name"); - assertEquals(application, actual); - } - - @Test - public void json() { - ApplicationRepresentation representation = ModelToRepresentation.toRepresentation(application); - representation.setId(null); - - RealmModel realm = realmManager.createRealm("copy"); - ApplicationModel copy = RepresentationToModel.createApplication(session, realm, representation, true); - - assertEquals(application, copy); - } - - @Test - public void testAddApplicationWithId() { - application = realm.addApplication("app-123", "application2"); - commit(); - application = realmManager.getRealm(realm.getId()).getApplicationById("app-123"); - Assert.assertNotNull(application); - } - - - public static void assertEquals(ApplicationModel expected, ApplicationModel actual) { - Assert.assertEquals(expected.getName(), actual.getName()); - Assert.assertEquals(expected.getBaseUrl(), actual.getBaseUrl()); - Assert.assertEquals(expected.getManagementUrl(), actual.getManagementUrl()); - Assert.assertEquals(expected.getDefaultRoles(), actual.getDefaultRoles()); - - Assert.assertTrue(expected.getRedirectUris().containsAll(actual.getRedirectUris())); - Assert.assertTrue(expected.getWebOrigins().containsAll(actual.getWebOrigins())); - Assert.assertTrue(expected.getRegisteredNodes().equals(actual.getRegisteredNodes())); - } - - public static void assertEquals(List expected, List actual) { - Assert.assertEquals(expected.size(), actual.size()); - Iterator exp = expected.iterator(); - Iterator act = actual.iterator(); - while (exp.hasNext()) { - Assert.assertEquals(exp.next().getName(), act.next().getName()); - } - } - -} - diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/CacheTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/CacheTest.java index f56582560c..1237cfa8ca 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/CacheTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/CacheTest.java @@ -3,7 +3,7 @@ package org.keycloak.testsuite.model; import org.junit.Assert; import org.junit.ClassRule; import org.junit.Test; -import org.keycloak.models.ApplicationModel; +import org.keycloak.models.ClientModel; import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; import org.keycloak.testsuite.rule.KeycloakRule; @@ -23,7 +23,7 @@ public class CacheTest { // load up cache KeycloakSession session = kc.startSession(); RealmModel realm = session.realms().getRealmByName("test"); - ApplicationModel testApp = realm.getApplicationByName("test-app"); + ClientModel testApp = realm.getClientByClientId("test-app"); Assert.assertNotNull(testApp); appId = testApp.getId(); Assert.assertTrue(testApp.isEnabled()); @@ -35,7 +35,7 @@ public class CacheTest { RealmModel realm = session.realms().getRealmByName("test"); Assert.assertTrue(realm instanceof org.keycloak.models.cache.RealmAdapter); realm.setAccessCodeLifespanLogin(200); - ApplicationModel testApp = realm.getApplicationByName("test-app"); + ClientModel testApp = realm.getClientByClientId("test-app"); Assert.assertNotNull(testApp); testApp.setEnabled(false); kc.stopSession(session, true); @@ -44,7 +44,7 @@ public class CacheTest { { KeycloakSession session = kc.startSession(); RealmModel realm = session.realms().getRealmByName("test"); - ApplicationModel testApp = session.realms().getApplicationById(appId, realm); + ClientModel testApp = session.realms().getClientById(appId, realm); Assert.assertFalse(testApp.isEnabled()); kc.stopSession(session, true); diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ClientModelTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ClientModelTest.java new file mode 100755 index 0000000000..f0fc63b14c --- /dev/null +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ClientModelTest.java @@ -0,0 +1,103 @@ +package org.keycloak.testsuite.model; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.keycloak.models.ClientModel; +import org.keycloak.models.RealmModel; +import org.keycloak.models.RoleModel; +import org.keycloak.models.utils.ModelToRepresentation; +import org.keycloak.models.utils.RepresentationToModel; +import org.keycloak.representations.idm.ClientRepresentation; +import org.keycloak.services.managers.ClientManager; + +import java.util.Iterator; +import java.util.List; + +/** + * @author Stian Thorgersen + */ +public class ClientModelTest extends AbstractModelTest { + private ClientModel client; + private RealmModel realm; + private ClientManager appManager; + + @Before + @Override + public void before() throws Exception { + super.before(); + appManager = new ClientManager(realmManager); + + realm = realmManager.createRealm("original"); + client = realm.addClient("application"); + client.setBaseUrl("http://base"); + client.setManagementUrl("http://management"); + client.setClientId("app-name"); + client.addRole("role-1"); + client.addRole("role-2"); + client.addRole("role-3"); + client.addDefaultRole("role-1"); + client.addDefaultRole("role-2"); + + client.addRedirectUri("redirect-1"); + client.addRedirectUri("redirect-2"); + + client.addWebOrigin("origin-1"); + client.addWebOrigin("origin-2"); + + client.registerNode("node1", 10); + client.registerNode("10.20.30.40", 50); + + client.updateClient(); + } + + @Test + public void persist() { + RealmModel persisted = realmManager.getRealm(realm.getId()); + + ClientModel actual = persisted.getClientNameMap().get("app-name"); + assertEquals(client, actual); + } + + @Test + public void json() { + ClientRepresentation representation = ModelToRepresentation.toRepresentation(client); + representation.setId(null); + + RealmModel realm = realmManager.createRealm("copy"); + ClientModel copy = RepresentationToModel.createClient(session, realm, representation, true); + + assertEquals(client, copy); + } + + @Test + public void testAddApplicationWithId() { + client = realm.addClient("app-123", "application2"); + commit(); + client = realmManager.getRealm(realm.getId()).getClientById("app-123"); + Assert.assertNotNull(client); + } + + + public static void assertEquals(ClientModel expected, ClientModel actual) { + Assert.assertEquals(expected.getClientId(), actual.getClientId()); + Assert.assertEquals(expected.getBaseUrl(), actual.getBaseUrl()); + Assert.assertEquals(expected.getManagementUrl(), actual.getManagementUrl()); + Assert.assertEquals(expected.getDefaultRoles(), actual.getDefaultRoles()); + + Assert.assertTrue(expected.getRedirectUris().containsAll(actual.getRedirectUris())); + Assert.assertTrue(expected.getWebOrigins().containsAll(actual.getWebOrigins())); + Assert.assertTrue(expected.getRegisteredNodes().equals(actual.getRegisteredNodes())); + } + + public static void assertEquals(List expected, List actual) { + Assert.assertEquals(expected.size(), actual.size()); + Iterator exp = expected.iterator(); + Iterator act = actual.iterator(); + while (exp.hasNext()) { + Assert.assertEquals(exp.next().getName(), act.next().getName()); + } + } + +} + diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/CompositeRolesModelTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/CompositeRolesModelTest.java index b99c310ba0..a23e048e24 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/CompositeRolesModelTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/CompositeRolesModelTest.java @@ -3,7 +3,7 @@ package org.keycloak.testsuite.model; import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import org.keycloak.models.ApplicationModel; +import org.keycloak.models.ClientModel; import org.keycloak.models.RealmModel; import org.keycloak.models.RoleModel; import org.keycloak.models.UserModel; @@ -58,7 +58,7 @@ public class CompositeRolesModelTest extends AbstractModelTest { RealmModel realm = realmManager.getRealm("TestComposites"); UserModel user = realmManager.getSession().users().getUserByUsername(username, realm); - ApplicationModel application = realm.getApplicationByName(applicationName); + ClientModel application = realm.getClientByClientId(applicationName); Set roleMappings = user.getRoleMappings(); Set scopeMappings = application.getScopeMappings(); @@ -95,7 +95,7 @@ public class CompositeRolesModelTest extends AbstractModelTest { if ("realm".equals(appName)) { return realm.getRole(roleName); } else { - return realm.getApplicationByName(appName).getRole(roleName); + return realm.getClientByClientId(appName).getRole(roleName); } } diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ImportTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ImportTest.java index e4d20f8733..54f4cbeedd 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ImportTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ImportTest.java @@ -5,7 +5,6 @@ import org.junit.FixMethodOrder; import org.junit.Test; import org.junit.runners.MethodSorters; import org.keycloak.constants.KerberosConstants; -import org.keycloak.models.ApplicationModel; import org.keycloak.models.ClientModel; import org.keycloak.models.Constants; import org.keycloak.models.FederatedIdentityModel; @@ -81,26 +80,23 @@ public class ImportTest extends AbstractModelTest { Assert.assertNotNull(user); Assert.assertEquals(0, session.users().getFederatedIdentities(user, realm).size()); - List resources = realm.getApplications(); - for (ApplicationModel app : resources) { - System.out.println("app: " + app.getName()); - } - Assert.assertEquals(5, resources.size()); + List resources = realm.getClients(); + Assert.assertEquals(6, resources.size()); // Test applications imported - ApplicationModel application = realm.getApplicationByName("Application"); - ApplicationModel otherApp = realm.getApplicationByName("OtherApp"); - ApplicationModel accountApp = realm.getApplicationByName(Constants.ACCOUNT_MANAGEMENT_APP); - ApplicationModel nonExisting = realm.getApplicationByName("NonExisting"); + ClientModel application = realm.getClientByClientId("Application"); + ClientModel otherApp = realm.getClientByClientId("OtherApp"); + ClientModel accountApp = realm.getClientByClientId(Constants.ACCOUNT_MANAGEMENT_CLIENT_ID); + ClientModel nonExisting = realm.getClientByClientId("NonExisting"); Assert.assertNotNull(application); Assert.assertNotNull(otherApp); Assert.assertNull(nonExisting); - Map apps = realm.getApplicationNameMap(); - Assert.assertEquals(5, apps.size()); - Assert.assertTrue(apps.values().contains(application)); - Assert.assertTrue(apps.values().contains(otherApp)); - Assert.assertTrue(apps.values().contains(accountApp)); - realm.getApplications().containsAll(apps.values()); + Map clients = realm.getClientNameMap(); + Assert.assertEquals(6, clients.size()); + Assert.assertTrue(clients.values().contains(application)); + Assert.assertTrue(clients.values().contains(otherApp)); + Assert.assertTrue(clients.values().contains(accountApp)); + realm.getClients().containsAll(clients.values()); Assert.assertEquals(50, application.getNodeReRegistrationTimeout()); Map appRegisteredNodes = application.getRegisteredNodes(); @@ -109,8 +105,8 @@ public class ImportTest extends AbstractModelTest { Assert.assertTrue(20 == appRegisteredNodes.get("172.10.15.20")); // Test finding applications by ID - Assert.assertNull(realm.getApplicationById("982734")); - Assert.assertEquals(application, realm.getApplicationById(application.getId())); + Assert.assertNull(realm.getClientById("982734")); + Assert.assertEquals(application, realm.getClientById(application.getId())); // Test role mappings @@ -134,12 +130,12 @@ public class ImportTest extends AbstractModelTest { Assert.assertEquals(1, realmRoles.size()); Assert.assertEquals("admin", realmRoles.iterator().next().getName()); - Set appRoles = admin.getApplicationRoleMappings(application); + Set appRoles = admin.getClientRoleMappings(application); Assert.assertEquals(1, appRoles.size()); Assert.assertEquals("app-admin", appRoles.iterator().next().getName()); // Test client - ClientModel oauthClient = realm.findClient("oauthclient"); + ClientModel oauthClient = realm.getClientByClientId("oauthclient"); Assert.assertEquals("clientpassword", oauthClient.getSecret()); Assert.assertEquals(true, oauthClient.isEnabled()); Assert.assertNotNull(oauthClient); @@ -153,7 +149,7 @@ public class ImportTest extends AbstractModelTest { Set realmScopes = oauthClient.getRealmScopeMappings(); Assert.assertTrue(realmScopes.contains(realm.getRole("admin"))); - Set appScopes = application.getApplicationScopeMappings(oauthClient); + Set appScopes = application.getClientScopeMappings(oauthClient); Assert.assertTrue(appScopes.contains(application.getRole("app-user"))); diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/MultipleRealmsTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/MultipleRealmsTest.java index 023a6fb8f5..1a4c660a37 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/MultipleRealmsTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/MultipleRealmsTest.java @@ -3,8 +3,7 @@ package org.keycloak.testsuite.model; import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import org.keycloak.models.ApplicationModel; -import org.keycloak.models.OAuthClientModel; +import org.keycloak.models.ClientModel; import org.keycloak.models.RealmModel; import org.keycloak.models.RoleModel; import org.keycloak.models.UserCredentialModel; @@ -66,17 +65,17 @@ public class MultipleRealmsTest extends AbstractModelTest { Assert.assertEquals(realm2, model.getRealm("id2")); Assert.assertEquals(realm2, model.getRealmByName("realm2")); - ApplicationModel r1app1 = realm1.getApplicationByName("app1"); - ApplicationModel r1app2 = realm1.getApplicationByName("app2"); - ApplicationModel r2app1 = realm2.getApplicationByName("app1"); - ApplicationModel r2app2 = realm2.getApplicationByName("app2"); + ClientModel r1app1 = realm1.getClientByClientId("app1"); + ClientModel r1app2 = realm1.getClientByClientId("app2"); + ClientModel r2app1 = realm2.getClientByClientId("app1"); + ClientModel r2app2 = realm2.getClientByClientId("app2"); - Assert.assertEquals(r1app1, realm1.getApplicationById(r1app1.getId())); - Assert.assertNull(realm2.getApplicationById(r1app1.getId())); + Assert.assertEquals(r1app1, realm1.getClientById(r1app1.getId())); + Assert.assertNull(realm2.getClientById(r1app1.getId())); - OAuthClientModel r2cl1 = realm2.getOAuthClient("cl1"); - Assert.assertEquals(r2cl1.getId(), realm2.getOAuthClientById(r2cl1.getId()).getId()); - Assert.assertNull(realm1.getOAuthClientById(r2cl1.getId())); + ClientModel r2cl1 = realm2.getClientByClientId("cl1"); + Assert.assertEquals(r2cl1.getId(), realm2.getClientById(r2cl1.getId()).getId()); + Assert.assertNull(realm1.getClientByClientId(r2cl1.getId())); RoleModel r1App1Role = r1app1.getRole("app1Role1"); Assert.assertEquals(r1App1Role, realm1.getRoleById(r1App1Role.getId())); @@ -88,8 +87,8 @@ public class MultipleRealmsTest extends AbstractModelTest { } private void createObjects(RealmModel realm) { - ApplicationModel app1 = realm.addApplication("app1"); - realm.addApplication("app2"); + ClientModel app1 = realm.addClient("app1"); + realm.addClient("app2"); realmManager.getSession().users().addUser(realm, "user1"); realmManager.getSession().users().addUser(realm, "user2"); @@ -100,7 +99,7 @@ public class MultipleRealmsTest extends AbstractModelTest { app1.addRole("app1Role1"); app1.addScopeMapping(realm.getRole("role1")); - realm.addOAuthClient("cl1"); + realm.addClient("cl1"); } } diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserModelTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserModelTest.java index d01dc7f610..b70e3fff59 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserModelTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserModelTest.java @@ -62,7 +62,7 @@ public class UserModelTest extends AbstractModelTest { @Test public void webOriginSetTest() { RealmModel realm = realmManager.createRealm("original"); - ClientModel client = realm.addApplication("user"); + ClientModel client = realm.addClient("user"); Assert.assertTrue(client.getWebOrigins().isEmpty()); @@ -78,7 +78,7 @@ public class UserModelTest extends AbstractModelTest { client.removeWebOrigin("origin-1"); Assert.assertTrue(client.getWebOrigins().isEmpty()); - client = realm.addOAuthClient("oauthclient2"); + client = realm.addClient("oauthclient2"); Assert.assertTrue(client.getWebOrigins().isEmpty()); diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserSessionProviderTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserSessionProviderTest.java index 35cf6fc106..b706203202 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserSessionProviderTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserSessionProviderTest.java @@ -83,7 +83,7 @@ public class UserSessionProviderTest { List clientSessions = session.sessions().getUserSession(realm, sessions[0].getId()).getClientSessions(); assertEquals(2, clientSessions.size()); - String client1 = realm.findClient("test-app").getId(); + String client1 = realm.getClientByClientId("test-app").getId(); ClientSessionModel session1; @@ -94,7 +94,7 @@ public class UserSessionProviderTest { } assertEquals(null, session1.getAction()); - assertEquals(realm.findClient("test-app").getClientId(), session1.getClient().getClientId()); + assertEquals(realm.getClientByClientId("test-app").getClientId(), session1.getClient().getClientId()); assertEquals(sessions[0].getId(), session1.getUserSession().getId()); assertEquals("http://redirect", session1.getRedirectUri()); assertEquals("state", session1.getNote(OIDCLoginProtocol.STATE_PARAM)); @@ -220,7 +220,7 @@ public class UserSessionProviderTest { } } - session.sessions().onClientRemoved(realm, realm.findClient("third-party")); + session.sessions().onClientRemoved(realm, realm.getClientByClientId("third-party")); resetSession(); for (String c : clientSessionsRemoved) { @@ -230,7 +230,7 @@ public class UserSessionProviderTest { assertNotNull(session.sessions().getClientSession(realm, c)); } - session.sessions().onClientRemoved(realm, realm.findClient("test-app")); + session.sessions().onClientRemoved(realm, realm.getClientByClientId("test-app")); resetSession(); for (String c : clientSessionsRemoved) { @@ -244,7 +244,7 @@ public class UserSessionProviderTest { @Test public void testRemoveUserSessionsByExpired() { session.sessions().getUserSessions(realm, session.users().getUserByUsername("user1", realm)); - ClientModel client = realm.findClient("test-app"); + ClientModel client = realm.getClientByClientId("test-app"); try { Set expired = new HashSet(); @@ -301,7 +301,7 @@ public class UserSessionProviderTest { realm.setAccessCodeLifespanLogin(30); // Login lifespan is largest - String clientSessionId = session.sessions().createClientSession(realm, realm.findClient("test-app")).getId(); + String clientSessionId = session.sessions().createClientSession(realm, realm.getClientByClientId("test-app")).getId(); resetSession(); Time.setOffset(25); @@ -320,7 +320,7 @@ public class UserSessionProviderTest { realm.setAccessCodeLifespanUserAction(40); Time.setOffset(0); - clientSessionId = session.sessions().createClientSession(realm, realm.findClient("test-app")).getId(); + clientSessionId = session.sessions().createClientSession(realm, realm.getClientByClientId("test-app")).getId(); resetSession(); Time.setOffset(35); @@ -339,7 +339,7 @@ public class UserSessionProviderTest { realm.setAccessCodeLifespan(50); Time.setOffset(0); - clientSessionId = session.sessions().createClientSession(realm, realm.findClient("test-app")).getId(); + clientSessionId = session.sessions().createClientSession(realm, realm.getClientByClientId("test-app")).getId(); resetSession(); Time.setOffset(45); @@ -367,8 +367,8 @@ public class UserSessionProviderTest { public void testGetByClient() { UserSessionModel[] sessions = createSessions(); - assertSessions(session.sessions().getUserSessions(realm, realm.findClient("test-app")), sessions[0], sessions[1], sessions[2]); - assertSessions(session.sessions().getUserSessions(realm, realm.findClient("third-party")), sessions[0]); + assertSessions(session.sessions().getUserSessions(realm, realm.getClientByClientId("test-app")), sessions[0], sessions[1], sessions[2]); + assertSessions(session.sessions().getUserSessions(realm, realm.getClientByClientId("third-party")), sessions[0]); } @Test @@ -377,7 +377,7 @@ public class UserSessionProviderTest { for (int i = 0; i < 25; i++) { Time.setOffset(i); UserSessionModel userSession = session.sessions().createUserSession(realm, session.users().getUserByUsername("user1", realm), "user1", "127.0.0." + i, "form", false, null, null); - ClientSessionModel clientSession = session.sessions().createClientSession(realm, realm.findClient("test-app")); + ClientSessionModel clientSession = session.sessions().createClientSession(realm, realm.getClientByClientId("test-app")); clientSession.setUserSession(userSession); clientSession.setRedirectUri("http://redirect"); clientSession.setRoles(new HashSet()); @@ -390,11 +390,11 @@ public class UserSessionProviderTest { resetSession(); - assertPaginatedSession(realm, realm.findClient("test-app"), 0, 1, 1); - assertPaginatedSession(realm, realm.findClient("test-app"), 0, 10, 10); - assertPaginatedSession(realm, realm.findClient("test-app"), 10, 10, 10); - assertPaginatedSession(realm, realm.findClient("test-app"), 20, 10, 5); - assertPaginatedSession(realm, realm.findClient("test-app"), 30, 10, 0); + assertPaginatedSession(realm, realm.getClientByClientId("test-app"), 0, 1, 1); + assertPaginatedSession(realm, realm.getClientByClientId("test-app"), 0, 10, 10); + assertPaginatedSession(realm, realm.getClientByClientId("test-app"), 10, 10, 10); + assertPaginatedSession(realm, realm.getClientByClientId("test-app"), 20, 10, 5); + assertPaginatedSession(realm, realm.getClientByClientId("test-app"), 30, 10, 0); } private void assertPaginatedSession(RealmModel realm, ClientModel client, int start, int max, int expectedSize) { @@ -416,8 +416,8 @@ public class UserSessionProviderTest { public void testGetCountByClient() { createSessions(); - assertEquals(3, session.sessions().getActiveUserSessions(realm, realm.findClient("test-app"))); - assertEquals(1, session.sessions().getActiveUserSessions(realm, realm.findClient("third-party"))); + assertEquals(3, session.sessions().getActiveUserSessions(realm, realm.getClientByClientId("test-app"))); + assertEquals(1, session.sessions().getActiveUserSessions(realm, realm.getClientByClientId("third-party"))); } @Test @@ -487,14 +487,14 @@ public class UserSessionProviderTest { roles.add("one"); roles.add("two"); - createClientSession(realm.findClient("test-app"), sessions[0], "http://redirect", "state", roles); - createClientSession(realm.findClient("third-party"), sessions[0], "http://redirect", "state", new HashSet()); + createClientSession(realm.getClientByClientId("test-app"), sessions[0], "http://redirect", "state", roles); + createClientSession(realm.getClientByClientId("third-party"), sessions[0], "http://redirect", "state", new HashSet()); sessions[1] = session.sessions().createUserSession(realm, session.users().getUserByUsername("user1", realm), "user1", "127.0.0.2", "form", true, null, null); - createClientSession(realm.findClient("test-app"), sessions[1], "http://redirect", "state", new HashSet()); + createClientSession(realm.getClientByClientId("test-app"), sessions[1], "http://redirect", "state", new HashSet()); sessions[2] = session.sessions().createUserSession(realm, session.users().getUserByUsername("user2", realm), "user2", "127.0.0.3", "form", true, null, null); - createClientSession(realm.findClient("test-app"), sessions[2], "http://redirect", "state", new HashSet()); + createClientSession(realm.getClientByClientId("test-app"), sessions[2], "http://redirect", "state", new HashSet()); resetSession(); diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/AccessTokenTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/AccessTokenTest.java index 7120b36fea..1fd4528565 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/AccessTokenTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/AccessTokenTest.java @@ -32,7 +32,6 @@ import org.keycloak.events.Details; import org.keycloak.events.Errors; import org.keycloak.events.Event; import org.keycloak.jose.jws.JWSInput; -import org.keycloak.models.ApplicationModel; import org.keycloak.models.ClientModel; import org.keycloak.models.KeycloakSession; import org.keycloak.models.ProtocolMapperModel; @@ -41,7 +40,6 @@ import org.keycloak.models.RoleModel; import org.keycloak.models.UserModel; import org.keycloak.protocol.oidc.OIDCLoginProtocolService; import org.keycloak.protocol.oidc.mappers.AddressMapper; -import org.keycloak.protocol.oidc.mappers.FullNameMapper; import org.keycloak.protocol.oidc.mappers.HardcodedClaim; import org.keycloak.protocol.oidc.mappers.HardcodedRole; import org.keycloak.protocol.oidc.mappers.RoleNameMapper; @@ -471,7 +469,7 @@ public class AccessTokenTest { { KeycloakSession session = keycloakRule.startSession(); RealmModel realm = session.realms().getRealmByName("test"); - ApplicationModel clientModel = realm.getApplicationByName("test-app"); + ClientModel clientModel = realm.getClientByClientId("test-app"); clientModel.setBearerOnly(true); session.getTransaction().commit(); session.close(); @@ -485,7 +483,7 @@ public class AccessTokenTest { { KeycloakSession session = keycloakRule.startSession(); RealmModel realm = session.realms().getRealmByName("test"); - ApplicationModel clientModel = realm.getApplicationByName("test-app"); + ClientModel clientModel = realm.getClientByClientId("test-app"); clientModel.setBearerOnly(false); session.getTransaction().commit(); session.close(); @@ -521,7 +519,7 @@ public class AccessTokenTest { { KeycloakSession session = keycloakRule.startSession(); RealmModel realm = session.realms().getRealmByName("test"); - ClientModel clientModel = realm.findClient("test-app"); + ClientModel clientModel = realm.getClientByClientId("test-app"); clientModel.setEnabled(false); session.getTransaction().commit(); session.close(); @@ -535,7 +533,7 @@ public class AccessTokenTest { { KeycloakSession session = keycloakRule.startSession(); RealmModel realm = session.realms().getRealmByName("test"); - ClientModel clientModel = realm.findClient("test-app"); + ClientModel clientModel = realm.getClientByClientId("test-app"); clientModel.setEnabled(true); session.getTransaction().commit(); session.close(); @@ -624,7 +622,7 @@ public class AccessTokenTest { user.setAttribute("postal_code", "02115"); user.setAttribute("country", "USA"); user.setAttribute("phone", "617-777-6666"); - ApplicationModel app = realm.getApplicationByName("test-app"); + ClientModel app = realm.getClientByClientId("test-app"); ProtocolMapperModel mapper = AddressMapper.createAddressMapper(true, true); app.addProtocolMapper(mapper); app.addProtocolMapper(HardcodedClaim.create("hard", "hard", "coded", "String", false, null, true, true)); @@ -687,7 +685,7 @@ public class AccessTokenTest { { KeycloakSession session = keycloakRule.startSession(); RealmModel realm = session.realms().getRealmByName("test"); - ApplicationModel app = realm.getApplicationByName("test-app"); + ClientModel app = realm.getClientByClientId("test-app"); for (ProtocolMapperModel model : app.getProtocolMappers()) { if (model.getName().equals("address") || model.getName().equals("hard") diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/AuthorizationCodeTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/AuthorizationCodeTest.java index 90a0e29783..0a70da0ef9 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/AuthorizationCodeTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/AuthorizationCodeTest.java @@ -96,7 +96,7 @@ public class AuthorizationCodeTest { keycloakRule.update(new KeycloakRule.KeycloakSetup() { @Override public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) { - appRealm.getApplicationNameMap().get("test-app").addRedirectUri(Constants.INSTALLED_APP_URN); + appRealm.getClientNameMap().get("test-app").addRedirectUri(Constants.INSTALLED_APP_URN); } }); oauth.redirectUri(Constants.INSTALLED_APP_URN); @@ -115,7 +115,7 @@ public class AuthorizationCodeTest { keycloakRule.update(new KeycloakRule.KeycloakSetup() { @Override public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) { - appRealm.getApplicationNameMap().get("test-app").removeRedirectUri(Constants.INSTALLED_APP_URN); + appRealm.getClientNameMap().get("test-app").removeRedirectUri(Constants.INSTALLED_APP_URN); } }); } @@ -125,7 +125,7 @@ public class AuthorizationCodeTest { keycloakRule.update(new KeycloakRule.KeycloakSetup() { @Override public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) { - appRealm.getApplicationNameMap().get("test-app").addRedirectUri(Constants.INSTALLED_APP_URN); + appRealm.getClientNameMap().get("test-app").addRedirectUri(Constants.INSTALLED_APP_URN); } }); oauth.redirectUri(Constants.INSTALLED_APP_URN); @@ -147,7 +147,7 @@ public class AuthorizationCodeTest { keycloakRule.update(new KeycloakRule.KeycloakSetup() { @Override public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) { - appRealm.getApplicationNameMap().get("test-app").removeRedirectUri(Constants.INSTALLED_APP_URN); + appRealm.getClientNameMap().get("test-app").removeRedirectUri(Constants.INSTALLED_APP_URN); } }); } @@ -157,7 +157,7 @@ public class AuthorizationCodeTest { keycloakRule.update(new KeycloakRule.KeycloakSetup() { @Override public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) { - appRealm.getApplicationByName("test-app").addRedirectUri(oauth.getRedirectUri()); + appRealm.getClientByClientId("test-app").addRedirectUri(oauth.getRedirectUri()); } }); diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/OAuthRedirectUriTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/OAuthRedirectUriTest.java index 9aa884ffe8..7cefa79c55 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/OAuthRedirectUriTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/OAuthRedirectUriTest.java @@ -26,7 +26,7 @@ import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; import org.keycloak.OAuth2Constants; -import org.keycloak.models.ApplicationModel; +import org.keycloak.models.ClientModel; import org.keycloak.models.Constants; import org.keycloak.models.RealmModel; import org.keycloak.services.managers.RealmManager; @@ -39,8 +39,6 @@ import org.keycloak.testsuite.rule.WebRule; import org.openqa.selenium.WebDriver; import java.io.IOException; -import java.util.HashMap; -import java.util.Map; /** * @author Viliam Rockai @@ -51,18 +49,18 @@ public class OAuthRedirectUriTest { public static KeycloakRule keycloakRule = new KeycloakRule(new KeycloakRule.KeycloakSetup() { @Override public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) { - ApplicationModel installedApp = appRealm.addApplication("test-installed"); + ClientModel installedApp = appRealm.addClient("test-installed"); installedApp.setEnabled(true); installedApp.addRedirectUri(Constants.INSTALLED_APP_URN); installedApp.addRedirectUri(Constants.INSTALLED_APP_URL); installedApp.setSecret("password"); - ApplicationModel installedApp2 = appRealm.addApplication("test-installed2"); + ClientModel installedApp2 = appRealm.addClient("test-installed2"); installedApp2.setEnabled(true); installedApp2.addRedirectUri(Constants.INSTALLED_APP_URL + "/myapp"); installedApp2.setSecret("password"); - ApplicationModel installedApp3 = appRealm.addApplication("test-wildcard"); + ClientModel installedApp3 = appRealm.addClient("test-wildcard"); installedApp3.setEnabled(true); installedApp3.addRedirectUri("http://example.com/foo/*"); installedApp3.addRedirectUri("http://localhost:8081/foo/*"); @@ -99,7 +97,7 @@ public class OAuthRedirectUriTest { keycloakRule.update(new KeycloakRule.KeycloakSetup() { @Override public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) { - appRealm.getApplicationNameMap().get("test-app").addRedirectUri("http://localhost:8081/app2"); + appRealm.getClientNameMap().get("test-app").addRedirectUri("http://localhost:8081/app2"); } }); @@ -113,7 +111,7 @@ public class OAuthRedirectUriTest { keycloakRule.update(new KeycloakRule.KeycloakSetup() { @Override public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) { - appRealm.getApplicationNameMap().get("test-app").removeRedirectUri("http://localhost:8081/app2"); + appRealm.getClientNameMap().get("test-app").removeRedirectUri("http://localhost:8081/app2"); } }); } @@ -124,7 +122,7 @@ public class OAuthRedirectUriTest { keycloakRule.update(new KeycloakRule.KeycloakSetup() { @Override public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) { - appRealm.getApplicationNameMap().get("test-app").removeRedirectUri("http://localhost:8081/app/*"); + appRealm.getClientNameMap().get("test-app").removeRedirectUri("http://localhost:8081/app/*"); } }); @@ -138,7 +136,7 @@ public class OAuthRedirectUriTest { keycloakRule.update(new KeycloakRule.KeycloakSetup() { @Override public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) { - appRealm.getApplicationNameMap().get("test-app").addRedirectUri("http://localhost:8081/app/*"); + appRealm.getClientNameMap().get("test-app").addRedirectUri("http://localhost:8081/app/*"); } }); } @@ -149,7 +147,7 @@ public class OAuthRedirectUriTest { keycloakRule.update(new KeycloakRule.KeycloakSetup() { @Override public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) { - appRealm.getApplicationNameMap().get("test-app").removeRedirectUri("http://localhost:8081/app/*"); + appRealm.getClientNameMap().get("test-app").removeRedirectUri("http://localhost:8081/app/*"); } }); @@ -163,7 +161,7 @@ public class OAuthRedirectUriTest { keycloakRule.update(new KeycloakRule.KeycloakSetup() { @Override public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) { - appRealm.getApplicationNameMap().get("test-app").addRedirectUri("http://localhost:8081/app/*"); + appRealm.getClientNameMap().get("test-app").addRedirectUri("http://localhost:8081/app/*"); } }); } diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/ResourceOwnerPasswordCredentialsGrantTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/ResourceOwnerPasswordCredentialsGrantTest.java index 7ab25689cb..90a88e2fc2 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/ResourceOwnerPasswordCredentialsGrantTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/ResourceOwnerPasswordCredentialsGrantTest.java @@ -6,7 +6,7 @@ import org.junit.Rule; import org.junit.Test; import org.keycloak.events.Details; import org.keycloak.events.Errors; -import org.keycloak.models.ApplicationModel; +import org.keycloak.models.ClientModel; import org.keycloak.models.RealmModel; import org.keycloak.models.UserCredentialModel; import org.keycloak.models.UserModel; @@ -31,7 +31,7 @@ public class ResourceOwnerPasswordCredentialsGrantTest { public static KeycloakRule keycloakRule = new KeycloakRule(new KeycloakRule.KeycloakSetup() { @Override public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) { - ApplicationModel app = appRealm.addApplication("resource-owner"); + ClientModel app = appRealm.addClient("resource-owner"); app.setSecret("secret"); appRealm.setPasswordCredentialGrantAllowed(true); diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/saml/SamlBindingTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/saml/SamlBindingTest.java index 126c465626..e91d58c0b4 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/saml/SamlBindingTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/saml/SamlBindingTest.java @@ -6,7 +6,7 @@ import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; import org.keycloak.Config; -import org.keycloak.models.ApplicationModel; +import org.keycloak.models.ClientModel; import org.keycloak.models.ClientSessionModel; import org.keycloak.models.Constants; import org.keycloak.models.KeycloakSession; @@ -259,7 +259,7 @@ public class SamlBindingTest { keycloakRule.update(new KeycloakRule.KeycloakSetup() { @Override public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) { - ApplicationModel app = appRealm.getApplicationByName("http://localhost:8081/employee/"); + ClientModel app = appRealm.getClientByClientId("http://localhost:8081/employee/"); for (ProtocolMapperModel mapper : app.getProtocolMappers()) { if (mapper.getName().equals("role-list")) { app.removeProtocolMapper(mapper); @@ -419,7 +419,7 @@ public class SamlBindingTest { RealmManager manager = new RealmManager(session); RealmModel adminRealm = manager.getRealm(Config.getAdminRealm()); - ApplicationModel adminConsole = adminRealm.getApplicationByName(Constants.ADMIN_CONSOLE_APPLICATION); + ClientModel adminConsole = adminRealm.getClientByClientId(Constants.ADMIN_CONSOLE_CLIENT_ID); TokenManager tm = new TokenManager(); UserModel admin = session.users().getUserByUsername("admin", adminRealm); ClientSessionModel clientSession = session.sessions().createClientSession(adminRealm, adminConsole); @@ -466,7 +466,7 @@ public class SamlBindingTest { Assert.assertNotNull(is); formData.addFormData("file", is, MediaType.APPLICATION_XML_TYPE); - WebTarget upload = adminRealms.path("demo/application-importers/saml2-entity-descriptor/upload"); + WebTarget upload = adminRealms.path("demo/client-importers/saml2-entity-descriptor/upload"); System.out.println(upload.getUri()); Response response = upload.request().post(Entity.entity(formData, MediaType.MULTIPART_FORM_DATA)); Assert.assertEquals(204, response.getStatus()); diff --git a/testsuite/integration/src/test/resources/testrealm.json b/testsuite/integration/src/test/resources/testrealm.json index cedc22dbae..c9b67085ba 100755 --- a/testsuite/integration/src/test/resources/testrealm.json +++ b/testsuite/integration/src/test/resources/testrealm.json @@ -27,7 +27,7 @@ "value" : "password" } ], "realmRoles": ["user"], - "applicationRoles": { + "clientRoles": { "test-app": [ "customer-user" ], "account": [ "view-profile", "manage-account" ] } @@ -41,22 +41,12 @@ "value" : "password" } ], "realmRoles": ["user"], - "applicationRoles": { + "clientRoles": { "test-app": [ "customer-user" ], "account": [ "view-profile", "manage-account" ] } } ], - "oauthClients" : [ - { - "name" : "third-party", - "enabled": true, - "redirectUris": [ - "http://localhost:8081/app/*" - ], - "secret": "password" - } - ], "scopeMappings": [ { "client": "third-party", @@ -67,9 +57,9 @@ "roles": ["user"] } ], - "applications": [ + "clients": [ { - "name": "test-app", + "clientId": "test-app", "enabled": true, "baseUrl": "http://localhost:8081/app", "redirectUris": [ @@ -77,7 +67,17 @@ ], "adminUrl": "http://localhost:8081/app/logout", "secret": "password" - } + }, + { + "clientId" : "third-party", + "enabled": true, + "consentRequired": true, + + "redirectUris": [ + "http://localhost:8081/app/*" + ], + "secret": "password" + } ], "roles" : { "realm" : [ @@ -90,7 +90,7 @@ "description": "Have Administrator privileges" } ], - "application" : { + "client" : { "test-app" : [ { "name": "customer-user", @@ -105,7 +105,7 @@ }, - "applicationScopeMappings": { + "clientScopeMappings": { "test-app": [ { "client": "third-party", diff --git a/testsuite/performance/src/test/java/org/keycloak/testsuite/performance/CreateRealmsWorker.java b/testsuite/performance/src/test/java/org/keycloak/testsuite/performance/CreateRealmsWorker.java index 14a106cb48..f913c156b4 100755 --- a/testsuite/performance/src/test/java/org/keycloak/testsuite/performance/CreateRealmsWorker.java +++ b/testsuite/performance/src/test/java/org/keycloak/testsuite/performance/CreateRealmsWorker.java @@ -3,7 +3,7 @@ package org.keycloak.testsuite.performance; import org.apache.jmeter.samplers.SampleResult; import org.apache.jorphan.logging.LoggingManager; import org.apache.log.Logger; -import org.keycloak.models.ApplicationModel; +import org.keycloak.models.ClientModel; import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; import org.keycloak.models.utils.RepresentationToModel; @@ -70,7 +70,7 @@ public class CreateRealmsWorker implements Worker { // Add applications for (int i=1 ; i<=appsPerRealm ; i++) { - ApplicationModel application = realm.addApplication(PerfTestUtils.getApplicationName(realmNumber, i)); + ClientModel application = realm.addClient(PerfTestUtils.getApplicationName(realmNumber, i)); for (int j=1 ; j<=rolesPerApp ; j++) { application.addRole(PerfTestUtils.getApplicationRoleName(realmNumber, i, j)); } diff --git a/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/CreateUsersJob.java b/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/CreateUsersJob.java index 115d5ae035..4c1bd01f21 100755 --- a/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/CreateUsersJob.java +++ b/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/CreateUsersJob.java @@ -1,6 +1,6 @@ package org.keycloak.test.tools.jobs; -import org.keycloak.models.ApplicationModel; +import org.keycloak.models.ClientModel; import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; import org.keycloak.models.RoleModel; @@ -26,7 +26,7 @@ public class CreateUsersJob extends UsersJob { } @Override - protected void runIteration(KeycloakSession session, RealmModel realm, Map apps, Set realmRoles, Map> appRoles, int counter) { + protected void runIteration(KeycloakSession session, RealmModel realm, Map apps, Set realmRoles, Map> appRoles, int counter) { String username = prefix + "-" + counter; UserModel user = session.users().addUser(realm, username); user.setEnabled(true); diff --git a/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/DeleteUsersJob.java b/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/DeleteUsersJob.java index e2711089d6..7e39f94d77 100755 --- a/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/DeleteUsersJob.java +++ b/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/DeleteUsersJob.java @@ -1,6 +1,6 @@ package org.keycloak.test.tools.jobs; -import org.keycloak.models.ApplicationModel; +import org.keycloak.models.ClientModel; import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; import org.keycloak.models.RoleModel; @@ -31,7 +31,7 @@ public class DeleteUsersJob extends UsersJob { } @Override - protected void runIteration(KeycloakSession session, RealmModel realm, Map apps, Set realmRoles, Map> appRoles, int counter) { + protected void runIteration(KeycloakSession session, RealmModel realm, Map apps, Set realmRoles, Map> appRoles, int counter) { session.users().removeUser(realm, users.next()); } } diff --git a/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/UpdateUsersJob.java b/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/UpdateUsersJob.java index 276b6d8e8d..6068764156 100755 --- a/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/UpdateUsersJob.java +++ b/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/UpdateUsersJob.java @@ -1,6 +1,6 @@ package org.keycloak.test.tools.jobs; -import org.keycloak.models.ApplicationModel; +import org.keycloak.models.ClientModel; import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; import org.keycloak.models.RoleModel; @@ -36,7 +36,7 @@ public class UpdateUsersJob extends UsersJob { } @Override - protected void runIteration(KeycloakSession session, RealmModel realm, Map apps, Set realmRoles, Map> appRoles, int counter) { + protected void runIteration(KeycloakSession session, RealmModel realm, Map apps, Set realmRoles, Map> appRoles, int counter) { String username = users.next().getUsername(); // Remove all role mappings first diff --git a/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/UsersJob.java b/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/UsersJob.java index b58a03bd29..d2f797ae8c 100755 --- a/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/UsersJob.java +++ b/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/UsersJob.java @@ -1,6 +1,6 @@ package org.keycloak.test.tools.jobs; -import org.keycloak.models.ApplicationModel; +import org.keycloak.models.ClientModel; import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSessionFactory; import org.keycloak.models.RealmModel; @@ -61,11 +61,11 @@ public abstract class UsersJob implements Runnable { session.getTransaction().begin(); RealmModel realm = new RealmManager(session).getRealmByName(realmName); - Map apps = realm.getApplicationNameMap(); + Map apps = realm.getClientNameMap(); Set realmRoles = realm.getRoles(); Map> appRoles = new HashMap>(); - for (Map.Entry appEntry : apps.entrySet()) { + for (Map.Entry appEntry : apps.entrySet()) { appRoles.put(appEntry.getKey(), appEntry.getValue().getRoles()); } @@ -86,7 +86,7 @@ public abstract class UsersJob implements Runnable { protected abstract void before(KeycloakSession keycloakSession); - protected abstract void runIteration(KeycloakSession session, RealmModel realm, Map apps, Set realmRoles, Map> appRoles, int counter); + protected abstract void runIteration(KeycloakSession session, RealmModel realm, Map apps, Set realmRoles, Map> appRoles, int counter); protected RoleModel findRole(Set roles, String roleName) { for (RoleModel role : roles) {