fix conflicts
This commit is contained in:
commit
f61fb4ba18
372 changed files with 12857 additions and 13271 deletions
|
@ -52,6 +52,11 @@
|
||||||
<artifactId>jboss-logging</artifactId>
|
<artifactId>jboss-logging</artifactId>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -112,11 +112,22 @@ public abstract class AbstractOAuth2IdentityProvider<C extends OAuth2IdentityPro
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String extractTokenFromResponse(String response, String tokenName) {
|
protected String extractTokenFromResponse(String response, String tokenName) {
|
||||||
|
if(response == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
if (response.startsWith("{")) {
|
if (response.startsWith("{")) {
|
||||||
try {
|
try {
|
||||||
return mapper.readTree(response).get(tokenName).getTextValue();
|
JsonNode node = mapper.readTree(response);
|
||||||
|
if(node.has(tokenName)){
|
||||||
|
String s = node.get(tokenName).getTextValue();
|
||||||
|
if(s == null || s.trim().isEmpty())
|
||||||
|
return null;
|
||||||
|
return s;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new IdentityBrokerException("Could not extract token [" + tokenName + "] from response [" + response + "].", e);
|
throw new IdentityBrokerException("Could not extract token [" + tokenName + "] from response [" + response + "] due: " + e.getMessage(), e);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Matcher matcher = Pattern.compile(tokenName + "=([^&]+)").matcher(response);
|
Matcher matcher = Pattern.compile(tokenName + "=([^&]+)").matcher(response);
|
||||||
|
@ -133,7 +144,7 @@ public abstract class AbstractOAuth2IdentityProvider<C extends OAuth2IdentityPro
|
||||||
String accessToken = extractTokenFromResponse(response, OAUTH2_PARAMETER_ACCESS_TOKEN);
|
String accessToken = extractTokenFromResponse(response, OAUTH2_PARAMETER_ACCESS_TOKEN);
|
||||||
|
|
||||||
if (accessToken == null) {
|
if (accessToken == null) {
|
||||||
throw new IdentityBrokerException("No access token from server.");
|
throw new IdentityBrokerException("No access token available in OAuth server response: " + response);
|
||||||
}
|
}
|
||||||
|
|
||||||
return doGetFederatedIdentity(accessToken);
|
return doGetFederatedIdentity(accessToken);
|
||||||
|
@ -144,7 +155,6 @@ public abstract class AbstractOAuth2IdentityProvider<C extends OAuth2IdentityPro
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
;
|
|
||||||
|
|
||||||
protected UriBuilder createAuthorizationUrl(AuthenticationRequest request) {
|
protected UriBuilder createAuthorizationUrl(AuthenticationRequest request) {
|
||||||
return UriBuilder.fromUri(getConfig().getAuthorizationUrl())
|
return UriBuilder.fromUri(getConfig().getAuthorizationUrl())
|
||||||
|
@ -155,9 +165,20 @@ public abstract class AbstractOAuth2IdentityProvider<C extends OAuth2IdentityPro
|
||||||
.queryParam(OAUTH2_PARAMETER_REDIRECT_URI, request.getRedirectUri());
|
.queryParam(OAUTH2_PARAMETER_REDIRECT_URI, request.getRedirectUri());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get JSON property as text. JSON numbers and booleans are converted to text. Empty string is converted to null.
|
||||||
|
*
|
||||||
|
* @param jsonNode to get property from
|
||||||
|
* @param name of property to get
|
||||||
|
* @return string value of the property or null.
|
||||||
|
*/
|
||||||
protected String getJsonProperty(JsonNode jsonNode, String name) {
|
protected String getJsonProperty(JsonNode jsonNode, String name) {
|
||||||
if (jsonNode.has(name)) {
|
if (jsonNode.has(name) && !jsonNode.get(name).isNull()) {
|
||||||
return jsonNode.get(name).asText();
|
String s = jsonNode.get(name).asText();
|
||||||
|
if(s != null && !s.isEmpty())
|
||||||
|
return s;
|
||||||
|
else
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -4,14 +4,12 @@ import org.keycloak.broker.oidc.util.SimpleHttp;
|
||||||
import org.keycloak.constants.AdapterConstants;
|
import org.keycloak.constants.AdapterConstants;
|
||||||
import org.keycloak.events.EventBuilder;
|
import org.keycloak.events.EventBuilder;
|
||||||
import org.keycloak.jose.jws.JWSInput;
|
import org.keycloak.jose.jws.JWSInput;
|
||||||
import org.keycloak.jose.jws.crypto.RSAProvider;
|
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.models.UserSessionModel;
|
import org.keycloak.models.UserSessionModel;
|
||||||
import org.keycloak.representations.adapters.action.AdminAction;
|
import org.keycloak.representations.adapters.action.AdminAction;
|
||||||
import org.keycloak.representations.adapters.action.LogoutAction;
|
import org.keycloak.representations.adapters.action.LogoutAction;
|
||||||
import org.keycloak.services.managers.AuthenticationManager;
|
import org.keycloak.services.managers.AuthenticationManager;
|
||||||
import org.keycloak.util.JsonSerialization;
|
import org.keycloak.util.JsonSerialization;
|
||||||
import org.keycloak.util.PemUtils;
|
|
||||||
|
|
||||||
import javax.ws.rs.POST;
|
import javax.ws.rs.POST;
|
||||||
import javax.ws.rs.Path;
|
import javax.ws.rs.Path;
|
||||||
|
@ -90,7 +88,7 @@ public class KeycloakOIDCIdentityProvider extends OIDCIdentityProvider {
|
||||||
@Override
|
@Override
|
||||||
public SimpleHttp generateTokenRequest(String authorizationCode) {
|
public SimpleHttp generateTokenRequest(String authorizationCode) {
|
||||||
return super.generateTokenRequest(authorizationCode)
|
return super.generateTokenRequest(authorizationCode)
|
||||||
.param(AdapterConstants.APPLICATION_SESSION_STATE, "n/a"); // hack to get backchannel logout to work
|
.param(AdapterConstants.CLIENT_SESSION_STATE, "n/a"); // hack to get backchannel logout to work
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,134 @@
|
||||||
|
/*
|
||||||
|
* 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.broker.oidc;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.codehaus.jackson.JsonNode;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.keycloak.broker.provider.BrokeredIdentityContext;
|
||||||
|
import org.keycloak.broker.provider.FederatedIdentity;
|
||||||
|
import org.keycloak.broker.provider.IdentityBrokerException;
|
||||||
|
import org.keycloak.models.IdentityProviderModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit test for {@link AbstractOAuth2IdentityProvider}
|
||||||
|
*
|
||||||
|
* @author Vlastimil Elias (velias at redhat dot com)
|
||||||
|
*/
|
||||||
|
public class AbstractOAuth2IdentityProviderTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void constructor_defaultScopeHandling(){
|
||||||
|
TestProvider tested = getTested();
|
||||||
|
|
||||||
|
//default scope is set from the provider if not provided in the configuration
|
||||||
|
Assert.assertEquals( tested.getDefaultScopes(), tested.getConfig().getDefaultScope());
|
||||||
|
|
||||||
|
//default scope is preserved if provided in the configuration
|
||||||
|
IdentityProviderModel model = new IdentityProviderModel();
|
||||||
|
OAuth2IdentityProviderConfig config = new OAuth2IdentityProviderConfig(model);
|
||||||
|
config.setDefaultScope("myscope");
|
||||||
|
tested = new TestProvider(config);
|
||||||
|
|
||||||
|
Assert.assertEquals("myscope", tested.getConfig().getDefaultScope());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getJsonProperty_asJsonNode() throws IOException {
|
||||||
|
TestProvider tested = getTested();
|
||||||
|
|
||||||
|
JsonNode jsonNode = tested
|
||||||
|
.asJsonNode("{\"nullone\":null, \"emptyone\":\"\", \"blankone\": \" \", \"withvalue\" : \"my value\", \"withbooleanvalue\" : true, \"withnumbervalue\" : 10}");
|
||||||
|
Assert.assertNull(tested.getJsonProperty(jsonNode, "nonexisting"));
|
||||||
|
Assert.assertNull(tested.getJsonProperty(jsonNode, "nullone"));
|
||||||
|
Assert.assertNull(tested.getJsonProperty(jsonNode, "emptyone"));
|
||||||
|
Assert.assertEquals(" ", tested.getJsonProperty(jsonNode, "blankone"));
|
||||||
|
Assert.assertEquals("my value", tested.getJsonProperty(jsonNode, "withvalue"));
|
||||||
|
Assert.assertEquals("true", tested.getJsonProperty(jsonNode, "withbooleanvalue"));
|
||||||
|
Assert.assertEquals("10", tested.getJsonProperty(jsonNode, "withnumbervalue"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IdentityBrokerException.class)
|
||||||
|
public void getFederatedIdentity_responseUrlLine_tokenNotFound() {
|
||||||
|
TestProvider tested = getTested();
|
||||||
|
tested.getFederatedIdentity("cosi=sss");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IdentityBrokerException.class)
|
||||||
|
public void getFederatedIdentity_responseJSON_tokenNotFound() {
|
||||||
|
TestProvider tested = getTested();
|
||||||
|
Map<String, String> notes = new HashMap<>();
|
||||||
|
tested.getFederatedIdentity("{\"cosi\":\"sss\"}");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IdentityBrokerException.class)
|
||||||
|
public void getFederatedIdentity_responseJSON_invalidFormat() {
|
||||||
|
TestProvider tested = getTested();
|
||||||
|
Map<String, String> 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<OAuth2IdentityProviderConfig> {
|
||||||
|
|
||||||
|
public TestProvider(OAuth2IdentityProviderConfig config) {
|
||||||
|
super(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getDefaultScopes() {
|
||||||
|
return "default";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected BrokeredIdentityContext doGetFederatedIdentity(String accessToken) {
|
||||||
|
return new BrokeredIdentityContext(accessToken);
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -36,5 +36,17 @@
|
||||||
<addPrimaryKey columnNames="IDP_MAPPER_ID, NAME" constraintName="CONSTRAINT_IDPMConfig" tableName="IDP_MAPPER_CONFIG"/>
|
<addPrimaryKey columnNames="IDP_MAPPER_ID, NAME" constraintName="CONSTRAINT_IDPMConfig" tableName="IDP_MAPPER_CONFIG"/>
|
||||||
<addForeignKeyConstraint baseColumnNames="REALM_ID" baseTableName="IDENTITY_PROVIDER_MAPPER" constraintName="FK_IDPM_REALM" referencedColumnNames="ID" referencedTableName="REALM"/>
|
<addForeignKeyConstraint baseColumnNames="REALM_ID" baseTableName="IDENTITY_PROVIDER_MAPPER" constraintName="FK_IDPM_REALM" referencedColumnNames="ID" referencedTableName="REALM"/>
|
||||||
<addForeignKeyConstraint baseColumnNames="IDP_MAPPER_ID" baseTableName="IDP_MAPPER_CONFIG" constraintName="FK_IDPMConfig" referencedColumnNames="ID" referencedTableName="IDENTITY_PROVIDER_MAPPER"/>
|
<addForeignKeyConstraint baseColumnNames="IDP_MAPPER_ID" baseTableName="IDP_MAPPER_CONFIG" constraintName="FK_IDPMConfig" referencedColumnNames="ID" referencedTableName="IDENTITY_PROVIDER_MAPPER"/>
|
||||||
|
|
||||||
|
<addColumn tableName="CLIENT">
|
||||||
|
<column name="CONSENT_REQUIRED" type="BOOLEAN" defaultValueBoolean="false">
|
||||||
|
<constraints nullable="false"/>
|
||||||
|
</column>
|
||||||
|
</addColumn>
|
||||||
|
<update tableName="CLIENT">
|
||||||
|
<column name="CONSENT_REQUIRED" valueBoolean="true"/>
|
||||||
|
<where>DTYPE = 'OAuthClientEntity'</where>
|
||||||
|
</update>
|
||||||
|
<dropColumn tableName="CLIENT" columnName="DTYPE"/>
|
||||||
|
<renameColumn tableName="CLIENT" newColumnName="CLIENT_ID" oldColumnName="NAME"/>
|
||||||
</changeSet>
|
</changeSet>
|
||||||
</databaseChangeLog>
|
</databaseChangeLog>
|
||||||
|
|
|
@ -3,9 +3,8 @@
|
||||||
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
|
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
|
||||||
version="1.0">
|
version="1.0">
|
||||||
<persistence-unit name="keycloak-default" transaction-type="RESOURCE_LOCAL">
|
<persistence-unit name="keycloak-default" transaction-type="RESOURCE_LOCAL">
|
||||||
<class>org.keycloak.models.jpa.entities.ApplicationEntity</class>
|
<class>org.keycloak.models.jpa.entities.ClientEntity</class>
|
||||||
<class>org.keycloak.models.jpa.entities.CredentialEntity</class>
|
<class>org.keycloak.models.jpa.entities.CredentialEntity</class>
|
||||||
<class>org.keycloak.models.jpa.entities.OAuthClientEntity</class>
|
|
||||||
<class>org.keycloak.models.jpa.entities.RealmEntity</class>
|
<class>org.keycloak.models.jpa.entities.RealmEntity</class>
|
||||||
<class>org.keycloak.models.jpa.entities.RealmAttributeEntity</class>
|
<class>org.keycloak.models.jpa.entities.RealmAttributeEntity</class>
|
||||||
<class>org.keycloak.models.jpa.entities.RequiredCredentialEntity</class>
|
<class>org.keycloak.models.jpa.entities.RequiredCredentialEntity</class>
|
||||||
|
|
|
@ -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_0_0_Final;
|
||||||
import org.keycloak.connections.mongo.updater.impl.updates.Update1_1_0_Beta1;
|
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_Beta1;
|
||||||
|
import org.keycloak.connections.mongo.updater.impl.updates.Update1_2_0_RC1;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
@ -28,7 +29,8 @@ public class DefaultMongoUpdaterProvider implements MongoUpdaterProvider {
|
||||||
private Class<? extends Update>[] updates = new Class[]{
|
private Class<? extends Update>[] updates = new Class[]{
|
||||||
Update1_0_0_Final.class,
|
Update1_0_0_Final.class,
|
||||||
Update1_1_0_Beta1.class,
|
Update1_1_0_Beta1.class,
|
||||||
Update1_2_0_Beta1.class
|
Update1_2_0_Beta1.class,
|
||||||
|
Update1_2_0_RC1.class
|
||||||
};
|
};
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -53,15 +53,8 @@ public abstract class Update {
|
||||||
log.debugv("Deleted entries from {0}", collection);
|
log.debugv("Deleted entries from {0}", collection);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String insertApplicationRole(DBCollection roles, String roleName, String applicationId) {
|
protected void renameCollection(String collection, String newName) {
|
||||||
BasicDBObject role = new BasicDBObject();
|
db.getCollection(collection).rename(newName);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLog(Logger log) {
|
public void setLog(Logger log) {
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
|
*/
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -33,8 +33,7 @@ public class DefaultMongoConnectionFactoryProvider implements MongoConnectionPro
|
||||||
"org.keycloak.models.entities.RequiredCredentialEntity",
|
"org.keycloak.models.entities.RequiredCredentialEntity",
|
||||||
"org.keycloak.models.entities.CredentialEntity",
|
"org.keycloak.models.entities.CredentialEntity",
|
||||||
"org.keycloak.models.entities.FederatedIdentityEntity",
|
"org.keycloak.models.entities.FederatedIdentityEntity",
|
||||||
"org.keycloak.models.mongo.keycloak.entities.MongoApplicationEntity",
|
"org.keycloak.models.mongo.keycloak.entities.MongoClientEntity",
|
||||||
"org.keycloak.models.mongo.keycloak.entities.MongoOAuthClientEntity",
|
|
||||||
"org.keycloak.models.sessions.mongo.entities.MongoUsernameLoginFailureEntity",
|
"org.keycloak.models.sessions.mongo.entities.MongoUsernameLoginFailureEntity",
|
||||||
"org.keycloak.models.sessions.mongo.entities.MongoUserSessionEntity",
|
"org.keycloak.models.sessions.mongo.entities.MongoUserSessionEntity",
|
||||||
"org.keycloak.models.sessions.mongo.entities.MongoClientSessionEntity",
|
"org.keycloak.models.sessions.mongo.entities.MongoClientSessionEntity",
|
||||||
|
|
|
@ -19,13 +19,13 @@ public interface AdapterConstants {
|
||||||
String AUTH_DATA_PARAM_NAME = "org.keycloak.json.adapterConfig";
|
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
|
// 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
|
// 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
|
// 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'
|
// 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";
|
public static final String KEYCLOAK_ADAPTER_STATE_COOKIE = "KEYCLOAK_ADAPTER_STATE";
|
||||||
|
|
|
@ -1,38 +0,0 @@
|
||||||
package org.keycloak.representations.idm;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
|
||||||
* @version $Revision: 1 $
|
|
||||||
*/
|
|
||||||
public class ApplicationMappingsRepresentation {
|
|
||||||
protected String applicationId;
|
|
||||||
protected String application;
|
|
||||||
|
|
||||||
protected List<RoleRepresentation> 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<RoleRepresentation> getMappings() {
|
|
||||||
return mappings;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMappings(List<RoleRepresentation> mappings) {
|
|
||||||
this.mappings = mappings;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,44 +1,14 @@
|
||||||
package org.keycloak.representations.idm;
|
package org.keycloak.representations.idm;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
* @version $Revision: 1 $
|
* @version $Revision: 1 $
|
||||||
*/
|
*/
|
||||||
public class ApplicationRepresentation {
|
@Deprecated
|
||||||
protected String id;
|
public class ApplicationRepresentation extends ClientRepresentation {
|
||||||
protected String name;
|
protected String name;
|
||||||
protected String adminUrl;
|
|
||||||
protected String baseUrl;
|
|
||||||
protected Boolean surrogateAuthRequired;
|
|
||||||
protected Boolean enabled;
|
|
||||||
protected String secret;
|
|
||||||
protected String[] defaultRoles;
|
|
||||||
protected List<String> redirectUris;
|
|
||||||
protected List<String> webOrigins;
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
protected ClaimRepresentation claims;
|
protected ClaimRepresentation claims;
|
||||||
protected Integer notBefore;
|
|
||||||
protected Boolean bearerOnly;
|
|
||||||
protected Boolean publicClient;
|
|
||||||
protected Boolean frontchannelLogout;
|
|
||||||
protected String protocol;
|
|
||||||
protected Map<String, String> attributes;
|
|
||||||
protected Boolean fullScopeAllowed;
|
|
||||||
protected Integer nodeReRegistrationTimeout;
|
|
||||||
protected Map<String, Integer> registeredNodes;
|
|
||||||
protected List<ClientIdentityProviderMappingRepresentation> identityProviders;
|
|
||||||
protected List<ProtocolMapperRepresentation> protocolMappers;
|
|
||||||
|
|
||||||
public String getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setId(String id) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
|
@ -48,70 +18,6 @@ public class ApplicationRepresentation {
|
||||||
this.name = name;
|
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<String> getRedirectUris() {
|
|
||||||
return redirectUris;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRedirectUris(List<String> redirectUris) {
|
|
||||||
this.redirectUris = redirectUris;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<String> getWebOrigins() {
|
|
||||||
return webOrigins;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setWebOrigins(List<String> webOrigins) {
|
|
||||||
this.webOrigins = webOrigins;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String[] getDefaultRoles() {
|
|
||||||
return defaultRoles;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDefaultRoles(String[] defaultRoles) {
|
|
||||||
this.defaultRoles = defaultRoles;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ClaimRepresentation getClaims() {
|
public ClaimRepresentation getClaims() {
|
||||||
return claims;
|
return claims;
|
||||||
}
|
}
|
||||||
|
@ -119,92 +25,4 @@ public class ApplicationRepresentation {
|
||||||
public void setClaims(ClaimRepresentation claims) {
|
public void setClaims(ClaimRepresentation claims) {
|
||||||
this.claims = 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<String, String> getAttributes() {
|
|
||||||
return attributes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAttributes(Map<String, String> attributes) {
|
|
||||||
this.attributes = attributes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Integer getNodeReRegistrationTimeout() {
|
|
||||||
return nodeReRegistrationTimeout;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setNodeReRegistrationTimeout(Integer nodeReRegistrationTimeout) {
|
|
||||||
this.nodeReRegistrationTimeout = nodeReRegistrationTimeout;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, Integer> getRegisteredNodes() {
|
|
||||||
return registeredNodes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRegisteredNodes(Map<String, Integer> registeredNodes) {
|
|
||||||
this.registeredNodes = registeredNodes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Boolean isFrontchannelLogout() {
|
|
||||||
return frontchannelLogout;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFrontchannelLogout(Boolean frontchannelLogout) {
|
|
||||||
this.frontchannelLogout = frontchannelLogout;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<ClientIdentityProviderMappingRepresentation> getIdentityProviders() {
|
|
||||||
return this.identityProviders;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setIdentityProviders(List<ClientIdentityProviderMappingRepresentation> identityProviders) {
|
|
||||||
this.identityProviders = identityProviders;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<ProtocolMapperRepresentation> getProtocolMappers() {
|
|
||||||
return protocolMappers;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setProtocolMappers(List<ProtocolMapperRepresentation> protocolMappers) {
|
|
||||||
this.protocolMappers = protocolMappers;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
package org.keycloak.representations.idm;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class ClientMappingsRepresentation {
|
||||||
|
protected String id;
|
||||||
|
protected String client;
|
||||||
|
|
||||||
|
protected List<RoleRepresentation> 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<RoleRepresentation> getMappings() {
|
||||||
|
return mappings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMappings(List<RoleRepresentation> mappings) {
|
||||||
|
this.mappings = mappings;
|
||||||
|
}
|
||||||
|
}
|
218
core/src/main/java/org/keycloak/representations/idm/ClientRepresentation.java
Executable file
218
core/src/main/java/org/keycloak/representations/idm/ClientRepresentation.java
Executable file
|
@ -0,0 +1,218 @@
|
||||||
|
package org.keycloak.representations.idm;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @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<String> redirectUris;
|
||||||
|
protected List<String> webOrigins;
|
||||||
|
protected Integer notBefore;
|
||||||
|
protected Boolean bearerOnly;
|
||||||
|
protected Boolean consentRequired;
|
||||||
|
protected Boolean directGrantsOnly;
|
||||||
|
protected Boolean publicClient;
|
||||||
|
protected Boolean frontchannelLogout;
|
||||||
|
protected String protocol;
|
||||||
|
protected Map<String, String> attributes;
|
||||||
|
protected Boolean fullScopeAllowed;
|
||||||
|
protected Integer nodeReRegistrationTimeout;
|
||||||
|
protected Map<String, Integer> registeredNodes;
|
||||||
|
protected List<ClientIdentityProviderMappingRepresentation> identityProviders;
|
||||||
|
protected List<ProtocolMapperRepresentation> 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<String> getRedirectUris() {
|
||||||
|
return redirectUris;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRedirectUris(List<String> redirectUris) {
|
||||||
|
this.redirectUris = redirectUris;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getWebOrigins() {
|
||||||
|
return webOrigins;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWebOrigins(List<String> 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<String, String> getAttributes() {
|
||||||
|
return attributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAttributes(Map<String, String> attributes) {
|
||||||
|
this.attributes = attributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getNodeReRegistrationTimeout() {
|
||||||
|
return nodeReRegistrationTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNodeReRegistrationTimeout(Integer nodeReRegistrationTimeout) {
|
||||||
|
this.nodeReRegistrationTimeout = nodeReRegistrationTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Integer> getRegisteredNodes() {
|
||||||
|
return registeredNodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRegisteredNodes(Map<String, Integer> registeredNodes) {
|
||||||
|
this.registeredNodes = registeredNodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean isFrontchannelLogout() {
|
||||||
|
return frontchannelLogout;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFrontchannelLogout(Boolean frontchannelLogout) {
|
||||||
|
this.frontchannelLogout = frontchannelLogout;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ClientIdentityProviderMappingRepresentation> getIdentityProviders() {
|
||||||
|
return this.identityProviders;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIdentityProviders(List<ClientIdentityProviderMappingRepresentation> identityProviders) {
|
||||||
|
this.identityProviders = identityProviders;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ProtocolMapperRepresentation> getProtocolMappers() {
|
||||||
|
return protocolMappers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProtocolMappers(List<ProtocolMapperRepresentation> protocolMappers) {
|
||||||
|
this.protocolMappers = protocolMappers;
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,7 +9,7 @@ import java.util.Map;
|
||||||
*/
|
*/
|
||||||
public class MappingsRepresentation {
|
public class MappingsRepresentation {
|
||||||
protected List<RoleRepresentation> realmMappings;
|
protected List<RoleRepresentation> realmMappings;
|
||||||
protected Map<String, ApplicationMappingsRepresentation> applicationMappings;
|
protected Map<String, ClientMappingsRepresentation> clientMappings;
|
||||||
|
|
||||||
public List<RoleRepresentation> getRealmMappings() {
|
public List<RoleRepresentation> getRealmMappings() {
|
||||||
return realmMappings;
|
return realmMappings;
|
||||||
|
@ -19,11 +19,11 @@ public class MappingsRepresentation {
|
||||||
this.realmMappings = realmMappings;
|
this.realmMappings = realmMappings;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, ApplicationMappingsRepresentation> getApplicationMappings() {
|
public Map<String, ClientMappingsRepresentation> getClientMappings() {
|
||||||
return applicationMappings;
|
return clientMappings;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setApplicationMappings(Map<String, ApplicationMappingsRepresentation> applicationMappings) {
|
public void setClientMappings(Map<String, ClientMappingsRepresentation> clientMappings) {
|
||||||
this.applicationMappings = applicationMappings;
|
this.clientMappings = clientMappings;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,157 +1,9 @@
|
||||||
package org.keycloak.representations.idm;
|
package org.keycloak.representations.idm;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
* @version $Revision: 1 $
|
* @version $Revision: 1 $
|
||||||
*/
|
*/
|
||||||
public class OAuthClientRepresentation {
|
|
||||||
protected String id;
|
|
||||||
protected String name;
|
|
||||||
protected List<String> redirectUris;
|
|
||||||
protected List<String> webOrigins;
|
|
||||||
protected Boolean enabled;
|
|
||||||
protected String secret;
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
protected ClaimRepresentation claims;
|
public class OAuthClientRepresentation extends ApplicationRepresentation {
|
||||||
protected Integer notBefore;
|
|
||||||
protected Boolean publicClient;
|
|
||||||
protected String protocol;
|
|
||||||
protected Map<String, String> attributes;
|
|
||||||
protected Boolean directGrantsOnly;
|
|
||||||
protected Boolean fullScopeAllowed;
|
|
||||||
protected Boolean frontchannelLogout;
|
|
||||||
protected List<ProtocolMapperRepresentation> protocolMappers;
|
|
||||||
private List<ClientIdentityProviderMappingRepresentation> 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<String> getRedirectUris() {
|
|
||||||
return redirectUris;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRedirectUris(List<String> redirectUris) {
|
|
||||||
this.redirectUris = redirectUris;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<String> getWebOrigins() {
|
|
||||||
return webOrigins;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setWebOrigins(List<String> 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<String, String> getAttributes() {
|
|
||||||
return attributes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAttributes(Map<String, String> attributes) {
|
|
||||||
this.attributes = attributes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Boolean isFrontchannelLogout() {
|
|
||||||
return frontchannelLogout;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFrontchannelLogout(Boolean frontchannelLogout) {
|
|
||||||
this.frontchannelLogout = frontchannelLogout;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<ClientIdentityProviderMappingRepresentation> getIdentityProviders() {
|
|
||||||
return this.identityProviders;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setIdentityProviders(List<ClientIdentityProviderMappingRepresentation> identityProviders) {
|
|
||||||
this.identityProviders = identityProviders;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<ProtocolMapperRepresentation> getProtocolMappers() {
|
|
||||||
return protocolMappers;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setProtocolMappers(List<ProtocolMapperRepresentation> protocolMappers) {
|
|
||||||
this.protocolMappers = protocolMappers;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,13 +25,6 @@ public class RealmRepresentation {
|
||||||
protected Boolean verifyEmail;
|
protected Boolean verifyEmail;
|
||||||
protected Boolean resetPasswordAllowed;
|
protected Boolean resetPasswordAllowed;
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
protected Boolean social;
|
|
||||||
@Deprecated
|
|
||||||
protected Boolean updateProfileOnInitialSocialLogin;
|
|
||||||
@Deprecated
|
|
||||||
protected Map<String, String> socialProviders;
|
|
||||||
|
|
||||||
protected Boolean userCacheEnabled;
|
protected Boolean userCacheEnabled;
|
||||||
protected Boolean realmCacheEnabled;
|
protected Boolean realmCacheEnabled;
|
||||||
|
|
||||||
|
@ -55,9 +48,8 @@ public class RealmRepresentation {
|
||||||
protected String passwordPolicy;
|
protected String passwordPolicy;
|
||||||
protected List<UserRepresentation> users;
|
protected List<UserRepresentation> users;
|
||||||
protected List<ScopeMappingRepresentation> scopeMappings;
|
protected List<ScopeMappingRepresentation> scopeMappings;
|
||||||
protected Map<String, List<ScopeMappingRepresentation>> applicationScopeMappings;
|
protected Map<String, List<ScopeMappingRepresentation>> clientScopeMappings;
|
||||||
protected List<ApplicationRepresentation> applications;
|
protected List<ClientRepresentation> clients;
|
||||||
protected List<OAuthClientRepresentation> oauthClients;
|
|
||||||
protected Map<String, String> browserSecurityHeaders;
|
protected Map<String, String> browserSecurityHeaders;
|
||||||
protected Map<String, String> smtpServer;
|
protected Map<String, String> smtpServer;
|
||||||
protected List<UserFederationProviderRepresentation> userFederationProviders;
|
protected List<UserFederationProviderRepresentation> userFederationProviders;
|
||||||
|
@ -76,6 +68,18 @@ public class RealmRepresentation {
|
||||||
protected Set<String> supportedLocales;
|
protected Set<String> supportedLocales;
|
||||||
protected String defaultLocale;
|
protected String defaultLocale;
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
protected Boolean social;
|
||||||
|
@Deprecated
|
||||||
|
protected Boolean updateProfileOnInitialSocialLogin;
|
||||||
|
@Deprecated
|
||||||
|
protected Map<String, String> socialProviders;
|
||||||
|
@Deprecated
|
||||||
|
protected Map<String, List<ScopeMappingRepresentation>> applicationScopeMappings;
|
||||||
|
@Deprecated
|
||||||
|
protected List<ApplicationRepresentation> applications;
|
||||||
|
@Deprecated
|
||||||
|
protected List<OAuthClientRepresentation> oauthClients;
|
||||||
|
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return id;
|
return id;
|
||||||
|
@ -101,14 +105,6 @@ public class RealmRepresentation {
|
||||||
return applications;
|
return applications;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ApplicationRepresentation resource(String name) {
|
|
||||||
ApplicationRepresentation resource = new ApplicationRepresentation();
|
|
||||||
if (applications == null) applications = new ArrayList<ApplicationRepresentation>();
|
|
||||||
applications.add(resource);
|
|
||||||
resource.setName(name);
|
|
||||||
return resource;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUsers(List<UserRepresentation> users) {
|
public void setUsers(List<UserRepresentation> users) {
|
||||||
this.users = users;
|
this.users = users;
|
||||||
}
|
}
|
||||||
|
@ -121,8 +117,12 @@ public class RealmRepresentation {
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setApplications(List<ApplicationRepresentation> applications) {
|
public List<ClientRepresentation> getClients() {
|
||||||
this.applications = applications;
|
return clients;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setClients(List<ClientRepresentation> clients) {
|
||||||
|
this.clients = clients;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Boolean isEnabled() {
|
public Boolean isEnabled() {
|
||||||
|
@ -321,22 +321,16 @@ public class RealmRepresentation {
|
||||||
this.resetPasswordAllowed = resetPassword;
|
this.resetPasswordAllowed = resetPassword;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public Boolean isSocial() {
|
public Boolean isSocial() {
|
||||||
return social;
|
return social;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSocial(Boolean social) {
|
@Deprecated
|
||||||
this.social = social;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Boolean isUpdateProfileOnInitialSocialLogin() {
|
public Boolean isUpdateProfileOnInitialSocialLogin() {
|
||||||
return updateProfileOnInitialSocialLogin;
|
return updateProfileOnInitialSocialLogin;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUpdateProfileOnInitialSocialLogin(Boolean updateProfileOnInitialSocialLogin) {
|
|
||||||
this.updateProfileOnInitialSocialLogin = updateProfileOnInitialSocialLogin;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, String> getBrowserSecurityHeaders() {
|
public Map<String, String> getBrowserSecurityHeaders() {
|
||||||
return browserSecurityHeaders;
|
return browserSecurityHeaders;
|
||||||
}
|
}
|
||||||
|
@ -345,14 +339,11 @@ public class RealmRepresentation {
|
||||||
this.browserSecurityHeaders = browserSecurityHeaders;
|
this.browserSecurityHeaders = browserSecurityHeaders;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public Map<String, String> getSocialProviders() {
|
public Map<String, String> getSocialProviders() {
|
||||||
return socialProviders;
|
return socialProviders;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSocialProviders(Map<String, String> socialProviders) {
|
|
||||||
this.socialProviders = socialProviders;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, String> getSmtpServer() {
|
public Map<String, String> getSmtpServer() {
|
||||||
return smtpServer;
|
return smtpServer;
|
||||||
}
|
}
|
||||||
|
@ -361,22 +352,24 @@ public class RealmRepresentation {
|
||||||
this.smtpServer = smtpServer;
|
this.smtpServer = smtpServer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public List<OAuthClientRepresentation> getOauthClients() {
|
public List<OAuthClientRepresentation> getOauthClients() {
|
||||||
return oauthClients;
|
return oauthClients;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOauthClients(List<OAuthClientRepresentation> oauthClients) {
|
public Map<String, List<ScopeMappingRepresentation>> getClientScopeMappings() {
|
||||||
this.oauthClients = oauthClients;
|
return clientScopeMappings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setClientScopeMappings(Map<String, List<ScopeMappingRepresentation>> clientScopeMappings) {
|
||||||
|
this.clientScopeMappings = clientScopeMappings;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public Map<String, List<ScopeMappingRepresentation>> getApplicationScopeMappings() {
|
public Map<String, List<ScopeMappingRepresentation>> getApplicationScopeMappings() {
|
||||||
return applicationScopeMappings;
|
return applicationScopeMappings;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setApplicationScopeMappings(Map<String, List<ScopeMappingRepresentation>> applicationScopeMappings) {
|
|
||||||
this.applicationScopeMappings = applicationScopeMappings;
|
|
||||||
}
|
|
||||||
|
|
||||||
public RolesRepresentation getRoles() {
|
public RolesRepresentation getRoles() {
|
||||||
return roles;
|
return roles;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,9 +17,10 @@ public class RoleRepresentation {
|
||||||
|
|
||||||
public static class Composites {
|
public static class Composites {
|
||||||
protected Set<String> realm;
|
protected Set<String> realm;
|
||||||
|
protected Map<String, List<String>> client;
|
||||||
|
@Deprecated
|
||||||
protected Map<String, List<String>> application;
|
protected Map<String, List<String>> application;
|
||||||
|
|
||||||
|
|
||||||
public Set<String> getRealm() {
|
public Set<String> getRealm() {
|
||||||
return realm;
|
return realm;
|
||||||
}
|
}
|
||||||
|
@ -28,12 +29,17 @@ public class RoleRepresentation {
|
||||||
this.realm = realm;
|
this.realm = realm;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, List<String>> getApplication() {
|
public Map<String, List<String>> getClient() {
|
||||||
return application;
|
return client;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setApplication(Map<String, List<String>> application) {
|
public void setClient(Map<String, List<String>> client) {
|
||||||
this.application = application;
|
this.client = client;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
public Map<String, List<String>> getApplication() {
|
||||||
|
return application;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,8 @@ import java.util.Map;
|
||||||
*/
|
*/
|
||||||
public class RolesRepresentation {
|
public class RolesRepresentation {
|
||||||
protected List<RoleRepresentation> realm;
|
protected List<RoleRepresentation> realm;
|
||||||
|
protected Map<String, List<RoleRepresentation>> client;
|
||||||
|
@Deprecated
|
||||||
protected Map<String, List<RoleRepresentation>> application;
|
protected Map<String, List<RoleRepresentation>> application;
|
||||||
|
|
||||||
public List<RoleRepresentation> getRealm() {
|
public List<RoleRepresentation> getRealm() {
|
||||||
|
@ -19,11 +21,16 @@ public class RolesRepresentation {
|
||||||
this.realm = realm;
|
this.realm = realm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Map<String, List<RoleRepresentation>> getClient() {
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setClient(Map<String, List<RoleRepresentation>> client) {
|
||||||
|
this.client = client;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public Map<String, List<RoleRepresentation>> getApplication() {
|
public Map<String, List<RoleRepresentation>> getApplication() {
|
||||||
return application;
|
return application;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setApplication(Map<String, List<RoleRepresentation>> application) {
|
|
||||||
this.application = application;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,10 +25,13 @@ public class UserRepresentation {
|
||||||
protected List<CredentialRepresentation> credentials;
|
protected List<CredentialRepresentation> credentials;
|
||||||
protected List<String> requiredActions;
|
protected List<String> requiredActions;
|
||||||
protected List<FederatedIdentityRepresentation> federatedIdentities;
|
protected List<FederatedIdentityRepresentation> federatedIdentities;
|
||||||
|
protected List<String> realmRoles;
|
||||||
|
protected Map<String, List<String>> clientRoles;
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
protected Map<String, List<String>> applicationRoles;
|
||||||
@Deprecated
|
@Deprecated
|
||||||
protected List<SocialLinkRepresentation> socialLinks;
|
protected List<SocialLinkRepresentation> socialLinks;
|
||||||
protected List<String> realmRoles;
|
|
||||||
protected Map<String, List<String>> applicationRoles;
|
|
||||||
|
|
||||||
public String getSelf() {
|
public String getSelf() {
|
||||||
return self;
|
return self;
|
||||||
|
@ -165,12 +168,17 @@ public class UserRepresentation {
|
||||||
this.realmRoles = realmRoles;
|
this.realmRoles = realmRoles;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, List<String>> getApplicationRoles() {
|
public Map<String, List<String>> getClientRoles() {
|
||||||
return applicationRoles;
|
return clientRoles;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setApplicationRoles(Map<String, List<String>> applicationRoles) {
|
public void setClientRoles(Map<String, List<String>> clientRoles) {
|
||||||
this.applicationRoles = applicationRoles;
|
this.clientRoles = clientRoles;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
public Map<String, List<String>> getApplicationRoles() {
|
||||||
|
return applicationRoles;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getFederationLink() {
|
public String getFederationLink() {
|
||||||
|
|
|
@ -15,7 +15,6 @@ public class UserSessionRepresentation {
|
||||||
private String ipAddress;
|
private String ipAddress;
|
||||||
private long start;
|
private long start;
|
||||||
private long lastAccess;
|
private long lastAccess;
|
||||||
private Map<String, String> applications = new HashMap<String, String>();
|
|
||||||
private Map<String, String> clients = new HashMap<String, String>();
|
private Map<String, String> clients = new HashMap<String, String>();
|
||||||
|
|
||||||
public String getId() {
|
public String getId() {
|
||||||
|
@ -58,14 +57,6 @@ public class UserSessionRepresentation {
|
||||||
this.lastAccess = lastAccess;
|
this.lastAccess = lastAccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, String> getApplications() {
|
|
||||||
return applications;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setApplications(Map<String, String> applications) {
|
|
||||||
this.applications = applications;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, String> getClients() {
|
public Map<String, String> getClients() {
|
||||||
return clients;
|
return clients;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,10 @@ public class Time {
|
||||||
return new Date(((long) time ) * 1000);
|
return new Date(((long) time ) * 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static long toMillis(int time) {
|
||||||
|
return ((long) time) * 1000;
|
||||||
|
}
|
||||||
|
|
||||||
public static void setOffset(int offset) {
|
public static void setOffset(int offset) {
|
||||||
Time.offset = offset;
|
Time.offset = offset;
|
||||||
}
|
}
|
||||||
|
|
28
dependencies/server-all/pom.xml
vendored
28
dependencies/server-all/pom.xml
vendored
|
@ -144,34 +144,6 @@
|
||||||
<artifactId>keycloak-kerberos-federation</artifactId>
|
<artifactId>keycloak-kerberos-federation</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.picketlink</groupId>
|
|
||||||
<artifactId>picketlink-common</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.picketlink</groupId>
|
|
||||||
<artifactId>picketlink-idm-api</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.picketlink</groupId>
|
|
||||||
<artifactId>picketlink-idm-impl</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.picketlink</groupId>
|
|
||||||
<artifactId>picketlink-idm-simple-schema</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- picketlink -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-picketlink-api</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-picketlink-ldap</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- saml -->
|
<!-- saml -->
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|
|
@ -259,14 +259,6 @@
|
||||||
<maven-resource group="org.keycloak" artifact="keycloak-ldap-federation"/>
|
<maven-resource group="org.keycloak" artifact="keycloak-ldap-federation"/>
|
||||||
</module-def>
|
</module-def>
|
||||||
|
|
||||||
<module-def name="org.keycloak.keycloak-picketlink-api">
|
|
||||||
<maven-resource group="org.keycloak" artifact="keycloak-picketlink-api"/>
|
|
||||||
</module-def>
|
|
||||||
|
|
||||||
<module-def name="org.keycloak.keycloak-picketlink-ldap">
|
|
||||||
<maven-resource group="org.keycloak" artifact="keycloak-picketlink-ldap"/>
|
|
||||||
</module-def>
|
|
||||||
|
|
||||||
<module-def name="org.keycloak.keycloak-saml-core">
|
<module-def name="org.keycloak.keycloak-saml-core">
|
||||||
<maven-resource group="org.keycloak" artifact="keycloak-saml-core"/>
|
<maven-resource group="org.keycloak" artifact="keycloak-saml-core"/>
|
||||||
</module-def>
|
</module-def>
|
||||||
|
|
|
@ -10,14 +10,9 @@
|
||||||
<module name="org.keycloak.keycloak-core"/>
|
<module name="org.keycloak.keycloak-core"/>
|
||||||
<module name="org.keycloak.keycloak-model-api"/>
|
<module name="org.keycloak.keycloak-model-api"/>
|
||||||
<module name="org.keycloak.keycloak-kerberos-federation"/>
|
<module name="org.keycloak.keycloak-kerberos-federation"/>
|
||||||
<module name="org.keycloak.keycloak-picketlink-api"/>
|
|
||||||
<module name="javax.ws.rs.api"/>
|
<module name="javax.ws.rs.api"/>
|
||||||
<module name="org.jboss.resteasy.resteasy-jaxrs"/>
|
<module name="org.jboss.resteasy.resteasy-jaxrs"/>
|
||||||
<module name="org.jboss.logging"/>
|
<module name="org.jboss.logging"/>
|
||||||
<module name="org.picketlink.common"/>
|
|
||||||
<module name="org.picketlink.idm.api"/>
|
|
||||||
<module name="org.picketlink.idm"/>
|
|
||||||
<module name="org.picketlink.idm.schema"/>
|
|
||||||
<module name="javax.api"/>
|
<module name="javax.api"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<module xmlns="urn:jboss:module:1.1" name="org.keycloak.keycloak-picketlink-api">
|
|
||||||
<resources>
|
|
||||||
<!-- Insert resources here -->
|
|
||||||
</resources>
|
|
||||||
<dependencies>
|
|
||||||
<module name="org.keycloak.keycloak-core"/>
|
|
||||||
<module name="org.keycloak.keycloak-model-api"/>
|
|
||||||
<module name="org.keycloak.keycloak-picketlink-api"/>
|
|
||||||
<module name="org.jboss.logging"/>
|
|
||||||
<module name="org.picketlink.common"/>
|
|
||||||
<module name="org.picketlink.idm.api"/>
|
|
||||||
<module name="org.picketlink.idm"/>
|
|
||||||
<module name="org.picketlink.idm.schema"/>
|
|
||||||
<module name="javax.api"/>
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
</module>
|
|
|
@ -1,21 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<module xmlns="urn:jboss:module:1.1" name="org.keycloak.keycloak-picketlink-ldap">
|
|
||||||
<resources>
|
|
||||||
<!-- Insert resources here -->
|
|
||||||
</resources>
|
|
||||||
<dependencies>
|
|
||||||
<module name="org.keycloak.keycloak-core"/>
|
|
||||||
<module name="org.keycloak.keycloak-model-api"/>
|
|
||||||
<module name="org.keycloak.keycloak-picketlink-api"/>
|
|
||||||
<module name="org.jboss.logging"/>
|
|
||||||
<module name="org.picketlink.common"/>
|
|
||||||
<module name="org.picketlink.idm.api"/>
|
|
||||||
<module name="org.picketlink.idm"/>
|
|
||||||
<module name="org.picketlink.idm.schema"/>
|
|
||||||
<module name="javax.api"/>
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
</module>
|
|
|
@ -48,8 +48,6 @@
|
||||||
<module name="org.keycloak.keycloak-model-sessions-jpa" services="import"/>
|
<module name="org.keycloak.keycloak-model-sessions-jpa" services="import"/>
|
||||||
<module name="org.keycloak.keycloak-model-sessions-mem" services="import"/>
|
<module name="org.keycloak.keycloak-model-sessions-mem" services="import"/>
|
||||||
<module name="org.keycloak.keycloak-model-sessions-mongo" services="import"/>
|
<module name="org.keycloak.keycloak-model-sessions-mongo" services="import"/>
|
||||||
<module name="org.keycloak.keycloak-picketlink-api" services="import"/>
|
|
||||||
<module name="org.keycloak.keycloak-picketlink-ldap" services="import"/>
|
|
||||||
<module name="org.keycloak.keycloak-saml-protocol" services="import"/>
|
<module name="org.keycloak.keycloak-saml-protocol" services="import"/>
|
||||||
<module name="org.keycloak.keycloak-services" export="true" services="import"/>
|
<module name="org.keycloak.keycloak-services" export="true" services="import"/>
|
||||||
<module name="org.keycloak.keycloak-social-core" services="import"/>
|
<module name="org.keycloak.keycloak-social-core" services="import"/>
|
||||||
|
|
|
@ -49,10 +49,8 @@
|
||||||
<module name="org.keycloak.keycloak-model-sessions-jpa" services="import"/>
|
<module name="org.keycloak.keycloak-model-sessions-jpa" services="import"/>
|
||||||
<module name="org.keycloak.keycloak-model-sessions-mem" services="import"/>
|
<module name="org.keycloak.keycloak-model-sessions-mem" services="import"/>
|
||||||
<module name="org.keycloak.keycloak-model-sessions-mongo" services="import"/>
|
<module name="org.keycloak.keycloak-model-sessions-mongo" services="import"/>
|
||||||
<module name="org.keycloak.keycloak-picketlink-api" services="import"/>
|
|
||||||
<module name="org.keycloak.keycloak-wildfly-extensions" services="import"/>
|
<module name="org.keycloak.keycloak-wildfly-extensions" services="import"/>
|
||||||
|
|
||||||
<module name="org.keycloak.keycloak-picketlink-ldap" services="import"/>
|
|
||||||
<module name="org.keycloak.keycloak-saml-protocol" services="import"/>
|
<module name="org.keycloak.keycloak-saml-protocol" services="import"/>
|
||||||
<module name="org.keycloak.keycloak-services" export="true" services="import"/>
|
<module name="org.keycloak.keycloak-services" export="true" services="import"/>
|
||||||
<module name="org.keycloak.keycloak-social-core" services="import"/>
|
<module name="org.keycloak.keycloak-social-core" services="import"/>
|
||||||
|
|
|
@ -40,9 +40,6 @@
|
||||||
<module name="org.keycloak.keycloak-model-sessions-jpa" services="import"/>
|
<module name="org.keycloak.keycloak-model-sessions-jpa" services="import"/>
|
||||||
<module name="org.keycloak.keycloak-model-sessions-mem" services="import"/>
|
<module name="org.keycloak.keycloak-model-sessions-mem" services="import"/>
|
||||||
<module name="org.keycloak.keycloak-model-sessions-mongo" services="import"/>
|
<module name="org.keycloak.keycloak-model-sessions-mongo" services="import"/>
|
||||||
<module name="org.keycloak.keycloak-picketlink-api" services="import"/>
|
|
||||||
|
|
||||||
<module name="org.keycloak.keycloak-picketlink-ldap" services="import"/>
|
|
||||||
<module name="org.keycloak.keycloak-saml-protocol" services="import"/>
|
<module name="org.keycloak.keycloak-saml-protocol" services="import"/>
|
||||||
<module name="org.keycloak.keycloak-services" export="true" services="import"/>
|
<module name="org.keycloak.keycloak-services" export="true" services="import"/>
|
||||||
<module name="org.keycloak.keycloak-social-core" services="import"/>
|
<module name="org.keycloak.keycloak-social-core" services="import"/>
|
||||||
|
|
|
@ -284,6 +284,15 @@
|
||||||
during the authentication process.
|
during the authentication process.
|
||||||
</entry>
|
</entry>
|
||||||
</row>
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry>
|
||||||
|
<literal>GUI order</literal>
|
||||||
|
</entry>
|
||||||
|
<entry>
|
||||||
|
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.
|
||||||
|
</entry>
|
||||||
|
</row>
|
||||||
<!--<row>-->
|
<!--<row>-->
|
||||||
<!--<entry>-->
|
<!--<entry>-->
|
||||||
<!--<literal>Store Tokens</literal>-->
|
<!--<literal>Store Tokens</literal>-->
|
||||||
|
|
|
@ -80,7 +80,7 @@
|
||||||
<programlisting>[<![CDATA[
|
<programlisting>[<![CDATA[
|
||||||
"theme": {
|
"theme": {
|
||||||
"default": "keycloak",
|
"default": "keycloak",
|
||||||
"staticMaxAge": 01,
|
"staticMaxAge": -1,
|
||||||
"cacheTemplates": false,
|
"cacheTemplates": false,
|
||||||
"cacheThemes": false,
|
"cacheThemes": false,
|
||||||
"folder": {
|
"folder": {
|
||||||
|
@ -205,7 +205,7 @@ import=common/keycloak
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
To deploy a theme as a module you need to create an jar (it's basically just a zip with jar extension) with
|
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 <literal>META/keycloak-server.json</literal> that describes the themes contained
|
the theme resources and a file <literal>META/keycloak-themes.json</literal> that describes the themes contained
|
||||||
in the archive. For example <literal>example-theme.jar</literal> with the contents:
|
in the archive. For example <literal>example-theme.jar</literal> with the contents:
|
||||||
<itemizedlist>
|
<itemizedlist>
|
||||||
<listitem>META-INF/keycloak-themes.json</listitem>
|
<listitem>META-INF/keycloak-themes.json</listitem>
|
||||||
|
@ -213,7 +213,7 @@ import=common/keycloak
|
||||||
<listitem>theme/example-theme/login/login.ftl</listitem>
|
<listitem>theme/example-theme/login/login.ftl</listitem>
|
||||||
<listitem>theme/example-theme/login/resources/css/styles.css</listitem>
|
<listitem>theme/example-theme/login/resources/css/styles.css</listitem>
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
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:
|
||||||
<programlisting>[<![CDATA[
|
<programlisting>[<![CDATA[
|
||||||
{
|
{
|
||||||
"themes": [{
|
"themes": [{
|
||||||
|
|
|
@ -17,12 +17,12 @@
|
||||||
"value": "password"
|
"value": "password"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"applicationRoles": {
|
"clientRoles": {
|
||||||
"realm-management": [ "realm-admin" ]
|
"realm-management": [ "realm-admin" ]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"applications": [
|
"clients": [
|
||||||
{
|
{
|
||||||
"name": "examples-admin-client",
|
"name": "examples-admin-client",
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<%@ page import="org.keycloak.admin.client.Keycloak" %>
|
<%@ page import="org.keycloak.admin.client.Keycloak" %>
|
||||||
<%@ 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.representations.idm.ApplicationRepresentation" %>
|
||||||
<%@ page import="org.keycloak.util.UriUtils" %>
|
<%@ page import="org.keycloak.util.UriUtils" %>
|
||||||
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1" %>
|
<%@ 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";
|
String authServer = UriUtils.getOrigin(request.getRequestURL().toString()) + "/auth";
|
||||||
|
|
||||||
Keycloak keycloak = Keycloak.getInstance(authServer, "example", "examples-admin-client", "password", "examples-admin-client", "password");
|
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("<h1>Applications</h1>");
|
out.println("<h1>Applications</h1>");
|
||||||
out.println("<ul>");
|
out.println("<ul>");
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
"value" : "password" }
|
"value" : "password" }
|
||||||
],
|
],
|
||||||
"realmRoles": [ "user","admin" ],
|
"realmRoles": [ "user","admin" ],
|
||||||
"applicationRoles": {
|
"clientRoles": {
|
||||||
"realm-management": [ "realm-admin" ]
|
"realm-management": [ "realm-admin" ]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"applications": [
|
"clients": [
|
||||||
{
|
{
|
||||||
"name": "basic-auth-service",
|
"name": "basic-auth-service",
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
"value" : "password" }
|
"value" : "password" }
|
||||||
],
|
],
|
||||||
"realmRoles": [ "user","admin" ],
|
"realmRoles": [ "user","admin" ],
|
||||||
"applicationRoles": {
|
"clientRoles": {
|
||||||
"realm-management": [ "realm-admin" ]
|
"realm-management": [ "realm-admin" ]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"applications": [
|
"clients": [
|
||||||
{
|
{
|
||||||
"name": "facebook-authentication",
|
"name": "facebook-authentication",
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
"value" : "password" }
|
"value" : "password" }
|
||||||
],
|
],
|
||||||
"realmRoles": [ "user","admin" ],
|
"realmRoles": [ "user","admin" ],
|
||||||
"applicationRoles": {
|
"clientRoles": {
|
||||||
"realm-management": [ "realm-admin" ]
|
"realm-management": [ "realm-admin" ]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"applications": [
|
"clients": [
|
||||||
{
|
{
|
||||||
"name": "google-authentication",
|
"name": "google-authentication",
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
"value" : "password" }
|
"value" : "password" }
|
||||||
],
|
],
|
||||||
"realmRoles": [ "user","admin" ],
|
"realmRoles": [ "user","admin" ],
|
||||||
"applicationRoles": {
|
"clientRoles": {
|
||||||
"realm-management": [ "realm-admin" ]
|
"realm-management": [ "realm-admin" ]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"applications": [
|
"clients": [
|
||||||
{
|
{
|
||||||
"name": "saml-broker-authentication",
|
"name": "saml-broker-authentication",
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"applications": [
|
"clients": [
|
||||||
{
|
{
|
||||||
"name": "http://localhost:8080/auth/realms/saml-broker-authentication-realm",
|
"name": "http://localhost:8080/auth/realms/saml-broker-authentication-realm",
|
||||||
"protocol": "saml",
|
"protocol": "saml",
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
"value" : "password" }
|
"value" : "password" }
|
||||||
],
|
],
|
||||||
"realmRoles": [ "user","admin" ],
|
"realmRoles": [ "user","admin" ],
|
||||||
"applicationRoles": {
|
"clientRoles": {
|
||||||
"realm-management": [ "realm-admin" ]
|
"realm-management": [ "realm-admin" ]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"applications": [
|
"clients": [
|
||||||
{
|
{
|
||||||
"name": "twitter-authentication",
|
"name": "twitter-authentication",
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
"value" : "password" }
|
"value" : "password" }
|
||||||
],
|
],
|
||||||
"realmRoles": [ "user" ],
|
"realmRoles": [ "user" ],
|
||||||
"applicationRoles": {
|
"clientRoles": {
|
||||||
"account": ["view-profile", "manage-account"]
|
"account": ["view-profile", "manage-account"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@
|
||||||
"roles": ["user"]
|
"roles": ["user"]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"applications": [
|
"clients": [
|
||||||
{
|
{
|
||||||
"name": "cordova",
|
"name": "cordova",
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
@ -50,7 +50,7 @@
|
||||||
"webOrigins": ["localhost"]
|
"webOrigins": ["localhost"]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"applicationScopeMappings": {
|
"clientScopeMappings": {
|
||||||
"account": [
|
"account": [
|
||||||
{
|
{
|
||||||
"client": "cordova",
|
"client": "cordova",
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
"value" : "password" }
|
"value" : "password" }
|
||||||
],
|
],
|
||||||
"realmRoles": [ "user" ],
|
"realmRoles": [ "user" ],
|
||||||
"applicationRoles": {
|
"clientRoles": {
|
||||||
"realm-management": [ "realm-admin" ]
|
"realm-management": [ "realm-admin" ]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,7 @@
|
||||||
"roles": ["user"]
|
"roles": ["user"]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"applications": [
|
"clients": [
|
||||||
{
|
{
|
||||||
"name": "angular-cors-product",
|
"name": "angular-cors-product",
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
@ -56,7 +56,7 @@
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"applicationScopeMappings": {
|
"clientScopeMappings": {
|
||||||
"realm-management": [
|
"realm-management": [
|
||||||
{
|
{
|
||||||
"client": "angular-cors-product",
|
"client": "angular-cors-product",
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
"value" : "password" }
|
"value" : "password" }
|
||||||
],
|
],
|
||||||
"realmRoles": [ "user" ],
|
"realmRoles": [ "user" ],
|
||||||
"applicationRoles": {
|
"clientRoles": {
|
||||||
"account": [ "manage-account" ]
|
"account": [ "manage-account" ]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -39,7 +39,7 @@
|
||||||
"value" : "password" }
|
"value" : "password" }
|
||||||
],
|
],
|
||||||
"realmRoles": [ "user" ],
|
"realmRoles": [ "user" ],
|
||||||
"applicationRoles": {
|
"clientRoles": {
|
||||||
"account": [ "manage-account" ]
|
"account": [ "manage-account" ]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -54,7 +54,7 @@
|
||||||
"value" : "password" }
|
"value" : "password" }
|
||||||
],
|
],
|
||||||
"realmRoles": [ "user" ],
|
"realmRoles": [ "user" ],
|
||||||
"applicationRoles": {
|
"clientRoles": {
|
||||||
"account": [ "manage-account" ]
|
"account": [ "manage-account" ]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -69,7 +69,7 @@
|
||||||
"value" : "password" }
|
"value" : "password" }
|
||||||
],
|
],
|
||||||
"realmRoles": [ "user","admin" ],
|
"realmRoles": [ "user","admin" ],
|
||||||
"applicationRoles": {
|
"clientRoles": {
|
||||||
"realm-management": [ "realm-admin" ]
|
"realm-management": [ "realm-admin" ]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -92,7 +92,7 @@
|
||||||
"roles": ["user"]
|
"roles": ["user"]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"applications": [
|
"clients": [
|
||||||
{
|
{
|
||||||
"name": "customer-portal",
|
"name": "customer-portal",
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
@ -146,12 +146,11 @@
|
||||||
"adminUrl": "/database",
|
"adminUrl": "/database",
|
||||||
"baseUrl": "/database",
|
"baseUrl": "/database",
|
||||||
"bearerOnly": true
|
"bearerOnly": true
|
||||||
}
|
},
|
||||||
],
|
|
||||||
"oauthClients": [
|
|
||||||
{
|
{
|
||||||
"name": "third-party",
|
"name": "third-party",
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
"consentRequired": true,
|
||||||
"redirectUris": [
|
"redirectUris": [
|
||||||
"/oauth-client/*",
|
"/oauth-client/*",
|
||||||
"/oauth-client-cdi/*"
|
"/oauth-client-cdi/*"
|
||||||
|
@ -162,11 +161,11 @@
|
||||||
"name": "admin-client",
|
"name": "admin-client",
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"publicClient": true,
|
"publicClient": true,
|
||||||
"directGrantsOnly": true
|
"directGrantsOnly": true,
|
||||||
|
"consentRequired": true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"applicationScopeMappings": {
|
"clientScopeMappings": {
|
||||||
"realm-management": [
|
"realm-management": [
|
||||||
{
|
{
|
||||||
"client": "admin-client",
|
"client": "admin-client",
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
"value" : "password" }
|
"value" : "password" }
|
||||||
],
|
],
|
||||||
"realmRoles": [ "user" ],
|
"realmRoles": [ "user" ],
|
||||||
"applicationRoles": {
|
"clientRoles": {
|
||||||
"account": [ "manage-account" ]
|
"account": [ "manage-account" ]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -39,7 +39,7 @@
|
||||||
"value" : "password" }
|
"value" : "password" }
|
||||||
],
|
],
|
||||||
"realmRoles": [ "user" ],
|
"realmRoles": [ "user" ],
|
||||||
"applicationRoles": {
|
"clientRoles": {
|
||||||
"account": [ "manage-account" ]
|
"account": [ "manage-account" ]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -54,7 +54,7 @@
|
||||||
"value" : "password" }
|
"value" : "password" }
|
||||||
],
|
],
|
||||||
"realmRoles": [ "user" ],
|
"realmRoles": [ "user" ],
|
||||||
"applicationRoles": {
|
"clientRoles": {
|
||||||
"account": [ "manage-account" ]
|
"account": [ "manage-account" ]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -69,7 +69,7 @@
|
||||||
"value" : "password" }
|
"value" : "password" }
|
||||||
],
|
],
|
||||||
"realmRoles": [ "user","admin" ],
|
"realmRoles": [ "user","admin" ],
|
||||||
"applicationRoles": {
|
"clientRoles": {
|
||||||
"realm-management": [ "realm-admin" ]
|
"realm-management": [ "realm-admin" ]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -84,7 +84,7 @@
|
||||||
"value" : "password" }
|
"value" : "password" }
|
||||||
],
|
],
|
||||||
"realmRoles": [ "user", "jmxAdmin" ],
|
"realmRoles": [ "user", "jmxAdmin" ],
|
||||||
"applicationRoles": {
|
"clientRoles": {
|
||||||
"account": [ "manage-account" ],
|
"account": [ "manage-account" ],
|
||||||
"realm-management": [ "realm-admin" ]
|
"realm-management": [ "realm-admin" ]
|
||||||
}
|
}
|
||||||
|
@ -134,7 +134,7 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"applications": [
|
"clients": [
|
||||||
{
|
{
|
||||||
"name": "customer-portal",
|
"name": "customer-portal",
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
@ -178,14 +178,13 @@
|
||||||
"adminUrl": "http://localhost:8383/admin-camel-endpoint",
|
"adminUrl": "http://localhost:8383/admin-camel-endpoint",
|
||||||
"baseUrl": "http://localhost:8383/admin-camel-endpoint",
|
"baseUrl": "http://localhost:8383/admin-camel-endpoint",
|
||||||
"bearerOnly": true
|
"bearerOnly": true
|
||||||
}
|
},
|
||||||
],
|
|
||||||
"oauthClients": [
|
|
||||||
{
|
{
|
||||||
"name": "ssh-jmx-admin-client",
|
"name": "ssh-jmx-admin-client",
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"publicClient": false,
|
"publicClient": false,
|
||||||
"directGrantsOnly": true,
|
"directGrantsOnly": true,
|
||||||
|
"consentRequired": true,
|
||||||
"secret": "password"
|
"secret": "password"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
"value" : "password" }
|
"value" : "password" }
|
||||||
],
|
],
|
||||||
"realmRoles": [ "user" ],
|
"realmRoles": [ "user" ],
|
||||||
"applicationRoles": {
|
"clientRoles": {
|
||||||
"account": ["view-profile", "manage-account"]
|
"account": ["view-profile", "manage-account"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@
|
||||||
"roles": ["user"]
|
"roles": ["user"]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"applications": [
|
"clients": [
|
||||||
{
|
{
|
||||||
"name": "js-console",
|
"name": "js-console",
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
@ -53,7 +53,7 @@
|
||||||
"webOrigins": []
|
"webOrigins": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"applicationScopeMappings": {
|
"clientScopeMappings": {
|
||||||
"account": [
|
"account": [
|
||||||
{
|
{
|
||||||
"client": "js-console",
|
"client": "js-console",
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
"roles": [ "user" ]
|
"roles": [ "user" ]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"applications": [
|
"clients": [
|
||||||
{
|
{
|
||||||
"name": "kerberos-app",
|
"name": "kerberos-app",
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
"value" : "user-tenant1" }
|
"value" : "user-tenant1" }
|
||||||
],
|
],
|
||||||
"realmRoles": [ "user" ],
|
"realmRoles": [ "user" ],
|
||||||
"applicationRoles": {
|
"clientRoles": {
|
||||||
"multi-tenant": [ "user" ]
|
"multi-tenant": [ "user" ]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
],
|
],
|
||||||
"applications": [
|
"clients": [
|
||||||
{
|
{
|
||||||
"name": "multi-tenant",
|
"name": "multi-tenant",
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
"value" : "user-tenant2" }
|
"value" : "user-tenant2" }
|
||||||
],
|
],
|
||||||
"realmRoles": [ "user" ],
|
"realmRoles": [ "user" ],
|
||||||
"applicationRoles": {
|
"clientRoles": {
|
||||||
"multi-tenant": [ "user" ]
|
"multi-tenant": [ "user" ]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,9 +41,9 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
],
|
],
|
||||||
"applications": [
|
"clients": [
|
||||||
{
|
{
|
||||||
"name": "multi-tenant",
|
"clientId": "multi-tenant",
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"adminUrl": "/multitenant/tenant2",
|
"adminUrl": "/multitenant/tenant2",
|
||||||
"baseUrl": "/multitenant/tenant2",
|
"baseUrl": "/multitenant/tenant2",
|
||||||
|
|
|
@ -25,9 +25,9 @@
|
||||||
"realmRoles": ["manager"]
|
"realmRoles": ["manager"]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"applications": [
|
"clients": [
|
||||||
{
|
{
|
||||||
"name": "http://localhost:8080/sales-post/",
|
"clientId": "http://localhost:8080/sales-post/",
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"fullScopeAllowed": true,
|
"fullScopeAllowed": true,
|
||||||
"protocol": "saml",
|
"protocol": "saml",
|
||||||
|
@ -41,7 +41,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "http://localhost:8080/sales-post-sig/",
|
"clientId": "http://localhost:8080/sales-post-sig/",
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"protocol": "saml",
|
"protocol": "saml",
|
||||||
"fullScopeAllowed": true,
|
"fullScopeAllowed": true,
|
||||||
|
@ -60,7 +60,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "http://localhost:8080/sales-post-enc/",
|
"clientId": "http://localhost:8080/sales-post-enc/",
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"protocol": "saml",
|
"protocol": "saml",
|
||||||
"fullScopeAllowed": true,
|
"fullScopeAllowed": true,
|
||||||
|
@ -82,7 +82,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "http://localhost:8080/employee/",
|
"clientId": "http://localhost:8080/employee/",
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"fullScopeAllowed": true,
|
"fullScopeAllowed": true,
|
||||||
"protocol": "saml",
|
"protocol": "saml",
|
||||||
|
@ -96,7 +96,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "http://localhost:8080/employee-sig/",
|
"clientId": "http://localhost:8080/employee-sig/",
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"protocol": "saml",
|
"protocol": "saml",
|
||||||
"fullScopeAllowed": true,
|
"fullScopeAllowed": true,
|
||||||
|
|
|
@ -6,10 +6,8 @@ import org.codehaus.jackson.JsonFactory;
|
||||||
import org.codehaus.jackson.JsonGenerator;
|
import org.codehaus.jackson.JsonGenerator;
|
||||||
import org.codehaus.jackson.map.ObjectMapper;
|
import org.codehaus.jackson.map.ObjectMapper;
|
||||||
import org.codehaus.jackson.map.SerializationConfig;
|
import org.codehaus.jackson.map.SerializationConfig;
|
||||||
import org.keycloak.models.ApplicationModel;
|
|
||||||
import org.keycloak.models.ClientModel;
|
import org.keycloak.models.ClientModel;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.OAuthClientModel;
|
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.models.RoleContainerModel;
|
import org.keycloak.models.RoleContainerModel;
|
||||||
import org.keycloak.models.RoleModel;
|
import org.keycloak.models.RoleModel;
|
||||||
|
@ -18,9 +16,8 @@ import org.keycloak.models.UserCredentialValueModel;
|
||||||
import org.keycloak.models.UserModel;
|
import org.keycloak.models.UserModel;
|
||||||
import org.keycloak.models.utils.ModelToRepresentation;
|
import org.keycloak.models.utils.ModelToRepresentation;
|
||||||
import org.keycloak.representations.idm.ApplicationRepresentation;
|
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.CredentialRepresentation;
|
||||||
import org.keycloak.representations.idm.OAuthClientRepresentation;
|
|
||||||
import org.keycloak.representations.idm.RealmRepresentation;
|
import org.keycloak.representations.idm.RealmRepresentation;
|
||||||
import org.keycloak.representations.idm.RoleRepresentation;
|
import org.keycloak.representations.idm.RoleRepresentation;
|
||||||
import org.keycloak.representations.idm.RolesRepresentation;
|
import org.keycloak.representations.idm.RolesRepresentation;
|
||||||
|
@ -57,52 +54,41 @@ public class ExportUtils {
|
||||||
rep.setEventsListeners(new LinkedList<String>(realm.getEventsListeners()));
|
rep.setEventsListeners(new LinkedList<String>(realm.getEventsListeners()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Applications
|
// Clients
|
||||||
List<ApplicationModel> applications = realm.getApplications();
|
List<ClientModel> clients = realm.getClients();
|
||||||
List<ApplicationRepresentation> appReps = new ArrayList<ApplicationRepresentation>();
|
List<ClientRepresentation> clientReps = new ArrayList<>();
|
||||||
for (ApplicationModel app : applications) {
|
for (ClientModel app : clients) {
|
||||||
ApplicationRepresentation appRep = exportApplication(app);
|
ClientRepresentation clientRep = exportClient(app);
|
||||||
appReps.add(appRep);
|
clientReps.add(clientRep);
|
||||||
}
|
}
|
||||||
rep.setApplications(appReps);
|
rep.setClients(clientReps);
|
||||||
|
|
||||||
// OAuth clients
|
|
||||||
List<OAuthClientModel> oauthClients = realm.getOAuthClients();
|
|
||||||
List<OAuthClientRepresentation> oauthClientReps = new ArrayList<OAuthClientRepresentation>();
|
|
||||||
for (OAuthClientModel oauthClient : oauthClients) {
|
|
||||||
OAuthClientRepresentation clientRep = ModelToRepresentation.toRepresentation(oauthClient);
|
|
||||||
clientRep.setSecret(oauthClient.getSecret());
|
|
||||||
oauthClientReps.add(clientRep);
|
|
||||||
}
|
|
||||||
rep.setOauthClients(oauthClientReps);
|
|
||||||
|
|
||||||
// Roles
|
// Roles
|
||||||
List<RoleRepresentation> realmRoleReps = null;
|
List<RoleRepresentation> realmRoleReps = null;
|
||||||
Map<String, List<RoleRepresentation>> appRolesReps = new HashMap<String, List<RoleRepresentation>>();
|
Map<String, List<RoleRepresentation>> clientRolesReps = new HashMap<>();
|
||||||
|
|
||||||
Set<RoleModel> realmRoles = realm.getRoles();
|
Set<RoleModel> realmRoles = realm.getRoles();
|
||||||
if (realmRoles != null && realmRoles.size() > 0) {
|
if (realmRoles != null && realmRoles.size() > 0) {
|
||||||
realmRoleReps = exportRoles(realmRoles);
|
realmRoleReps = exportRoles(realmRoles);
|
||||||
}
|
}
|
||||||
for (ApplicationModel app : applications) {
|
for (ClientModel client : clients) {
|
||||||
Set<RoleModel> currentAppRoles = app.getRoles();
|
Set<RoleModel> currentAppRoles = client.getRoles();
|
||||||
List<RoleRepresentation> currentAppRoleReps = exportRoles(currentAppRoles);
|
List<RoleRepresentation> currentAppRoleReps = exportRoles(currentAppRoles);
|
||||||
appRolesReps.put(app.getName(), currentAppRoleReps);
|
clientRolesReps.put(client.getClientId(), currentAppRoleReps);
|
||||||
}
|
}
|
||||||
|
|
||||||
RolesRepresentation rolesRep = new RolesRepresentation();
|
RolesRepresentation rolesRep = new RolesRepresentation();
|
||||||
if (realmRoleReps != null) {
|
if (realmRoleReps != null) {
|
||||||
rolesRep.setRealm(realmRoleReps);
|
rolesRep.setRealm(realmRoleReps);
|
||||||
}
|
}
|
||||||
if (appRolesReps.size() > 0) {
|
if (clientRolesReps.size() > 0) {
|
||||||
rolesRep.setApplication(appRolesReps);
|
rolesRep.setClient(clientRolesReps);
|
||||||
}
|
}
|
||||||
rep.setRoles(rolesRep);
|
rep.setRoles(rolesRep);
|
||||||
|
|
||||||
// Scopes
|
// Scopes
|
||||||
List<ClientModel> allClients = new ArrayList<ClientModel>(applications);
|
List<ClientModel> allClients = new ArrayList<>(clients);
|
||||||
allClients.addAll(realm.getOAuthClients());
|
Map<String, List<ScopeMappingRepresentation>> clientScopeReps = new HashMap<>();
|
||||||
Map<String, List<ScopeMappingRepresentation>> appScopeReps = new HashMap<String, List<ScopeMappingRepresentation>>();
|
|
||||||
|
|
||||||
for (ClientModel client : allClients) {
|
for (ClientModel client : allClients) {
|
||||||
Set<RoleModel> clientScopes = client.getScopeMappings();
|
Set<RoleModel> clientScopes = client.getScopeMappings();
|
||||||
|
@ -114,12 +100,12 @@ public class ExportUtils {
|
||||||
}
|
}
|
||||||
scopeMappingRep.role(scope.getName());
|
scopeMappingRep.role(scope.getName());
|
||||||
} else {
|
} else {
|
||||||
ApplicationModel app = (ApplicationModel)scope.getContainer();
|
ClientModel app = (ClientModel)scope.getContainer();
|
||||||
String appName = app.getName();
|
String appName = app.getClientId();
|
||||||
List<ScopeMappingRepresentation> currentAppScopes = appScopeReps.get(appName);
|
List<ScopeMappingRepresentation> currentAppScopes = clientScopeReps.get(appName);
|
||||||
if (currentAppScopes == null) {
|
if (currentAppScopes == null) {
|
||||||
currentAppScopes = new ArrayList<ScopeMappingRepresentation>();
|
currentAppScopes = new ArrayList<>();
|
||||||
appScopeReps.put(appName, currentAppScopes);
|
clientScopeReps.put(appName, currentAppScopes);
|
||||||
}
|
}
|
||||||
|
|
||||||
ScopeMappingRepresentation currentClientScope = null;
|
ScopeMappingRepresentation currentClientScope = null;
|
||||||
|
@ -139,8 +125,8 @@ public class ExportUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (appScopeReps.size() > 0) {
|
if (clientScopeReps.size() > 0) {
|
||||||
rep.setApplicationScopeMappings(appScopeReps);
|
rep.setClientScopeMappings(clientScopeReps);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally users if needed
|
// Finally users if needed
|
||||||
|
@ -162,14 +148,13 @@ public class ExportUtils {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Full export of application including claims and secret
|
* Full export of application including claims and secret
|
||||||
* @param app
|
* @param client
|
||||||
* @return full ApplicationRepresentation
|
* @return full ApplicationRepresentation
|
||||||
*/
|
*/
|
||||||
public static ApplicationRepresentation exportApplication(ApplicationModel app) {
|
public static ClientRepresentation exportClient(ClientModel client) {
|
||||||
ApplicationRepresentation appRep = ModelToRepresentation.toRepresentation(app);
|
ClientRepresentation clientRep = ModelToRepresentation.toRepresentation(client);
|
||||||
|
clientRep.setSecret(client.getSecret());
|
||||||
appRep.setSecret(app.getSecret());
|
return clientRep;
|
||||||
return appRep;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<RoleRepresentation> exportRoles(Collection<RoleModel> roles) {
|
public static List<RoleRepresentation> exportRoles(Collection<RoleModel> roles) {
|
||||||
|
@ -201,27 +186,27 @@ public class ExportUtils {
|
||||||
Set<RoleModel> composites = role.getComposites();
|
Set<RoleModel> composites = role.getComposites();
|
||||||
if (composites != null && composites.size() > 0) {
|
if (composites != null && composites.size() > 0) {
|
||||||
Set<String> compositeRealmRoles = null;
|
Set<String> compositeRealmRoles = null;
|
||||||
Map<String, List<String>> compositeAppRoles = null;
|
Map<String, List<String>> compositeClientRoles = null;
|
||||||
|
|
||||||
for (RoleModel composite : composites) {
|
for (RoleModel composite : composites) {
|
||||||
RoleContainerModel crContainer = composite.getContainer();
|
RoleContainerModel crContainer = composite.getContainer();
|
||||||
if (crContainer instanceof RealmModel) {
|
if (crContainer instanceof RealmModel) {
|
||||||
|
|
||||||
if (compositeRealmRoles == null) {
|
if (compositeRealmRoles == null) {
|
||||||
compositeRealmRoles = new HashSet<String>();
|
compositeRealmRoles = new HashSet<>();
|
||||||
}
|
}
|
||||||
compositeRealmRoles.add(composite.getName());
|
compositeRealmRoles.add(composite.getName());
|
||||||
} else {
|
} else {
|
||||||
if (compositeAppRoles == null) {
|
if (compositeClientRoles == null) {
|
||||||
compositeAppRoles = new HashMap<String, List<String>>();
|
compositeClientRoles = new HashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
ApplicationModel app = (ApplicationModel)crContainer;
|
ClientModel app = (ClientModel)crContainer;
|
||||||
String appName = app.getName();
|
String appName = app.getClientId();
|
||||||
List<String> currentAppComposites = compositeAppRoles.get(appName);
|
List<String> currentAppComposites = compositeClientRoles.get(appName);
|
||||||
if (currentAppComposites == null) {
|
if (currentAppComposites == null) {
|
||||||
currentAppComposites = new ArrayList<String>();
|
currentAppComposites = new ArrayList<>();
|
||||||
compositeAppRoles.put(appName, currentAppComposites);
|
compositeClientRoles.put(appName, currentAppComposites);
|
||||||
}
|
}
|
||||||
currentAppComposites.add(composite.getName());
|
currentAppComposites.add(composite.getName());
|
||||||
}
|
}
|
||||||
|
@ -231,8 +216,8 @@ public class ExportUtils {
|
||||||
if (compositeRealmRoles != null) {
|
if (compositeRealmRoles != null) {
|
||||||
compRep.setRealm(compositeRealmRoles);
|
compRep.setRealm(compositeRealmRoles);
|
||||||
}
|
}
|
||||||
if (compositeAppRoles != null) {
|
if (compositeClientRoles != null) {
|
||||||
compRep.setApplication(compositeAppRoles);
|
compRep.setClient(compositeClientRoles);
|
||||||
}
|
}
|
||||||
|
|
||||||
roleRep.setComposites(compRep);
|
roleRep.setComposites(compRep);
|
||||||
|
@ -263,29 +248,29 @@ public class ExportUtils {
|
||||||
|
|
||||||
// Role mappings
|
// Role mappings
|
||||||
Set<RoleModel> roles = user.getRoleMappings();
|
Set<RoleModel> roles = user.getRoleMappings();
|
||||||
List<String> realmRoleNames = new ArrayList<String>();
|
List<String> realmRoleNames = new ArrayList<>();
|
||||||
Map<String, List<String>> appRoleNames = new HashMap<String, List<String>>();
|
Map<String, List<String>> clientRoleNames = new HashMap<>();
|
||||||
for (RoleModel role : roles) {
|
for (RoleModel role : roles) {
|
||||||
if (role.getContainer() instanceof RealmModel) {
|
if (role.getContainer() instanceof RealmModel) {
|
||||||
realmRoleNames.add(role.getName());
|
realmRoleNames.add(role.getName());
|
||||||
} else {
|
} else {
|
||||||
ApplicationModel app = (ApplicationModel)role.getContainer();
|
ClientModel client = (ClientModel)role.getContainer();
|
||||||
String appName = app.getName();
|
String clientId = client.getClientId();
|
||||||
List<String> currentAppRoles = appRoleNames.get(appName);
|
List<String> currentClientRoles = clientRoleNames.get(clientId);
|
||||||
if (currentAppRoles == null) {
|
if (currentClientRoles == null) {
|
||||||
currentAppRoles = new ArrayList<String>();
|
currentClientRoles = new ArrayList<>();
|
||||||
appRoleNames.put(appName, currentAppRoles);
|
clientRoleNames.put(clientId, currentClientRoles);
|
||||||
}
|
}
|
||||||
|
|
||||||
currentAppRoles.add(role.getName());
|
currentClientRoles.add(role.getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (realmRoleNames.size() > 0) {
|
if (realmRoleNames.size() > 0) {
|
||||||
userRep.setRealmRoles(realmRoleNames);
|
userRep.setRealmRoles(realmRoleNames);
|
||||||
}
|
}
|
||||||
if (appRoleNames.size() > 0) {
|
if (clientRoleNames.size() > 0) {
|
||||||
userRep.setApplicationRoles(appRoleNames);
|
userRep.setClientRoles(clientRoleNames);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Credentials
|
// Credentials
|
||||||
|
|
|
@ -8,7 +8,7 @@ import org.jboss.logging.Logger;
|
||||||
import org.keycloak.Config;
|
import org.keycloak.Config;
|
||||||
import org.keycloak.exportimport.Strategy;
|
import org.keycloak.exportimport.Strategy;
|
||||||
import org.keycloak.models.AdminRoles;
|
import org.keycloak.models.AdminRoles;
|
||||||
import org.keycloak.models.ApplicationModel;
|
import org.keycloak.models.ClientModel;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.models.RealmProvider;
|
import org.keycloak.models.RealmProvider;
|
||||||
|
@ -54,7 +54,7 @@ public class ImportUtils {
|
||||||
if (Config.getAdminRealm().equals(realm.getId())) {
|
if (Config.getAdminRealm().equals(realm.getId())) {
|
||||||
// Delete all masterAdmin apps due to foreign key constraints
|
// Delete all masterAdmin apps due to foreign key constraints
|
||||||
for (RealmModel currRealm : model.getRealms()) {
|
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
|
// 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
|
// We just imported master realm. All 'masterAdminApps' need to be refreshed
|
||||||
RealmModel adminRealm = realm;
|
RealmModel adminRealm = realm;
|
||||||
for (RealmModel currentRealm : model.getRealms()) {
|
for (RealmModel currentRealm : model.getRealms()) {
|
||||||
ApplicationModel masterApp = adminRealm.getApplicationByName(KeycloakModelUtils.getMasterRealmAdminApplicationName(currentRealm));
|
ClientModel masterApp = adminRealm.getClientByClientId(KeycloakModelUtils.getMasterRealmAdminApplicationClientId(currentRealm));
|
||||||
if (masterApp != null) {
|
if (masterApp != null) {
|
||||||
currentRealm.setMasterAdminApp(masterApp);
|
currentRealm.setMasterAdminClient(masterApp);
|
||||||
} else {
|
} else {
|
||||||
setupMasterAdminManagement(model, currentRealm);
|
setupMasterAdminManagement(model, currentRealm);
|
||||||
}
|
}
|
||||||
|
@ -91,9 +91,9 @@ public class ImportUtils {
|
||||||
} else {
|
} else {
|
||||||
// Need to refresh masterApp for current realm
|
// Need to refresh masterApp for current realm
|
||||||
RealmModel adminRealm = model.getRealm(adminRealmId);
|
RealmModel adminRealm = model.getRealm(adminRealmId);
|
||||||
ApplicationModel masterApp = adminRealm.getApplicationByName(KeycloakModelUtils.getMasterRealmAdminApplicationName(realm));
|
ClientModel masterApp = adminRealm.getClientByClientId(KeycloakModelUtils.getMasterRealmAdminApplicationClientId(realm));
|
||||||
if (masterApp != null) {
|
if (masterApp != null) {
|
||||||
realm.setMasterAdminApp(masterApp);
|
realm.setMasterAdminClient(masterApp);
|
||||||
} else {
|
} else {
|
||||||
setupMasterAdminManagement(model, realm);
|
setupMasterAdminManagement(model, realm);
|
||||||
}
|
}
|
||||||
|
@ -119,9 +119,9 @@ public class ImportUtils {
|
||||||
}
|
}
|
||||||
adminRole.setDescription("${role_"+AdminRoles.ADMIN+"}");
|
adminRole.setDescription("${role_"+AdminRoles.ADMIN+"}");
|
||||||
|
|
||||||
ApplicationModel realmAdminApp = KeycloakModelUtils.createApplication(adminRealm, KeycloakModelUtils.getMasterRealmAdminApplicationName(realm));
|
ClientModel realmAdminApp = KeycloakModelUtils.createClient(adminRealm, KeycloakModelUtils.getMasterRealmAdminApplicationClientId(realm));
|
||||||
realmAdminApp.setBearerOnly(true);
|
realmAdminApp.setBearerOnly(true);
|
||||||
realm.setMasterAdminApp(realmAdminApp);
|
realm.setMasterAdminClient(realmAdminApp);
|
||||||
|
|
||||||
for (String r : AdminRoles.ALL_REALM_ROLES) {
|
for (String r : AdminRoles.ALL_REALM_ROLES) {
|
||||||
RoleModel role = realmAdminApp.addRole(r);
|
RoleModel role = realmAdminApp.addRole(r);
|
||||||
|
@ -220,7 +220,7 @@ public class ImportUtils {
|
||||||
|
|
||||||
private static void importUsers(KeycloakSession session, RealmProvider model, String realmName, List<UserRepresentation> userReps) {
|
private static void importUsers(KeycloakSession session, RealmProvider model, String realmName, List<UserRepresentation> userReps) {
|
||||||
RealmModel realm = model.getRealmByName(realmName);
|
RealmModel realm = model.getRealmByName(realmName);
|
||||||
Map<String, ApplicationModel> apps = realm.getApplicationNameMap();
|
Map<String, ClientModel> apps = realm.getClientNameMap();
|
||||||
for (UserRepresentation user : userReps) {
|
for (UserRepresentation user : userReps) {
|
||||||
RepresentationToModel.createUser(session, realm, user, apps);
|
RepresentationToModel.createUser(session, realm, user, apps);
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,12 +31,6 @@
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-picketlink-api</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.jboss.resteasy</groupId>
|
<groupId>org.jboss.resteasy</groupId>
|
||||||
<artifactId>resteasy-jaxrs</artifactId>
|
<artifactId>resteasy-jaxrs</artifactId>
|
||||||
|
@ -61,27 +55,6 @@
|
||||||
<artifactId>jboss-logging</artifactId>
|
<artifactId>jboss-logging</artifactId>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.picketlink</groupId>
|
|
||||||
<artifactId>picketlink-common</artifactId>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.picketlink</groupId>
|
|
||||||
<artifactId>picketlink-idm-api</artifactId>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.picketlink</groupId>
|
|
||||||
<artifactId>picketlink-idm-impl</artifactId>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.picketlink</groupId>
|
|
||||||
<artifactId>picketlink-idm-simple-schema</artifactId>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|
|
@ -3,6 +3,10 @@ package org.keycloak.federation.ldap;
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.keycloak.federation.kerberos.impl.KerberosUsernamePasswordAuthenticator;
|
import org.keycloak.federation.kerberos.impl.KerberosUsernamePasswordAuthenticator;
|
||||||
import org.keycloak.federation.kerberos.impl.SPNEGOAuthenticator;
|
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.federation.ldap.kerberos.LDAPProviderKerberosConfig;
|
||||||
import org.keycloak.models.CredentialValidationOutput;
|
import org.keycloak.models.CredentialValidationOutput;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
@ -16,12 +20,6 @@ import org.keycloak.models.UserFederationProvider;
|
||||||
import org.keycloak.models.UserFederationProviderModel;
|
import org.keycloak.models.UserFederationProviderModel;
|
||||||
import org.keycloak.models.UserModel;
|
import org.keycloak.models.UserModel;
|
||||||
import org.keycloak.constants.KerberosConstants;
|
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.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
@ -38,23 +36,21 @@ import java.util.Set;
|
||||||
*/
|
*/
|
||||||
public class LDAPFederationProvider implements UserFederationProvider {
|
public class LDAPFederationProvider implements UserFederationProvider {
|
||||||
private static final Logger logger = Logger.getLogger(LDAPFederationProvider.class);
|
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 LDAPFederationProviderFactory factory;
|
||||||
protected KeycloakSession session;
|
protected KeycloakSession session;
|
||||||
protected UserFederationProviderModel model;
|
protected UserFederationProviderModel model;
|
||||||
protected PartitionManager partitionManager;
|
protected LDAPIdentityStore ldapIdentityStore;
|
||||||
protected EditMode editMode;
|
protected EditMode editMode;
|
||||||
protected LDAPProviderKerberosConfig kerberosConfig;
|
protected LDAPProviderKerberosConfig kerberosConfig;
|
||||||
|
|
||||||
protected final Set<String> supportedCredentialTypes = new HashSet<String>();
|
protected final Set<String> supportedCredentialTypes = new HashSet<String>();
|
||||||
|
|
||||||
public LDAPFederationProvider(LDAPFederationProviderFactory factory, KeycloakSession session, UserFederationProviderModel model, PartitionManager partitionManager) {
|
public LDAPFederationProvider(LDAPFederationProviderFactory factory, KeycloakSession session, UserFederationProviderModel model, LDAPIdentityStore ldapIdentityStore) {
|
||||||
this.factory = factory;
|
this.factory = factory;
|
||||||
this.session = session;
|
this.session = session;
|
||||||
this.model = model;
|
this.model = model;
|
||||||
this.partitionManager = partitionManager;
|
this.ldapIdentityStore = ldapIdentityStore;
|
||||||
this.kerberosConfig = new LDAPProviderKerberosConfig(model);
|
this.kerberosConfig = new LDAPProviderKerberosConfig(model);
|
||||||
String editModeString = model.getConfig().get(LDAPConstants.EDIT_MODE);
|
String editModeString = model.getConfig().get(LDAPConstants.EDIT_MODE);
|
||||||
if (editModeString == null) {
|
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() {
|
public KeycloakSession getSession() {
|
||||||
return session;
|
return session;
|
||||||
}
|
}
|
||||||
|
@ -87,8 +73,8 @@ public class LDAPFederationProvider implements UserFederationProvider {
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PartitionManager getPartitionManager() {
|
public LDAPIdentityStore getLdapIdentityStore() {
|
||||||
return partitionManager;
|
return this.ldapIdentityStore;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -125,22 +111,18 @@ public class LDAPFederationProvider implements UserFederationProvider {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean synchronizeRegistrations() {
|
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
|
@Override
|
||||||
public UserModel register(RealmModel realm, UserModel user) {
|
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");
|
if (!synchronizeRegistrations()) throw new IllegalStateException("Registration is not supported by this ldap server");
|
||||||
|
|
||||||
try {
|
LDAPUser ldapUser = LDAPUtils.addUser(this.ldapIdentityStore, user.getUsername(), user.getFirstName(), user.getLastName(), user.getEmail());
|
||||||
User picketlinkUser = LDAPUtils.addUser(this.partitionManager, user.getUsername(), user.getFirstName(), user.getLastName(), user.getEmail());
|
user.setAttribute(LDAPConstants.LDAP_ID, ldapUser.getId());
|
||||||
user.setAttribute(LDAP_ID, picketlinkUser.getId());
|
user.setAttribute(LDAPConstants.LDAP_ENTRY_DN, ldapUser.getEntryDN());
|
||||||
return proxy(user);
|
return proxy(user);
|
||||||
} catch (IdentityManagementException ie) {
|
|
||||||
throw convertIDMException(ie);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -150,58 +132,53 @@ public class LDAPFederationProvider implements UserFederationProvider {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
return LDAPUtils.removeUser(this.ldapIdentityStore, user.getUsername());
|
||||||
return LDAPUtils.removeUser(partitionManager, user.getUsername());
|
|
||||||
} catch (IdentityManagementException ie) {
|
|
||||||
throw convertIDMException(ie);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> searchByAttributes(Map<String, String> attributes, RealmModel realm, int maxResults) {
|
public List<UserModel> searchByAttributes(Map<String, String> attributes, RealmModel realm, int maxResults) {
|
||||||
List<UserModel> searchResults =new LinkedList<UserModel>();
|
List<UserModel> searchResults =new LinkedList<UserModel>();
|
||||||
try {
|
|
||||||
Map<String, User> plUsers = searchPicketlink(attributes, maxResults);
|
Map<String, LDAPUser> ldapUsers = searchLDAP(attributes, maxResults);
|
||||||
for (User user : plUsers.values()) {
|
for (LDAPUser ldapUser : ldapUsers.values()) {
|
||||||
if (session.userStorage().getUserByUsername(user.getLoginName(), realm) == null) {
|
if (session.userStorage().getUserByUsername(ldapUser.getLoginName(), realm) == null) {
|
||||||
UserModel imported = importUserFromPicketlink(realm, user);
|
UserModel imported = importUserFromLDAP(realm, ldapUser);
|
||||||
searchResults.add(imported);
|
searchResults.add(imported);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (IdentityManagementException ie) {
|
|
||||||
throw convertIDMException(ie);
|
|
||||||
}
|
|
||||||
return searchResults;
|
return searchResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Map<String, User> searchPicketlink(Map<String, String> attributes, int maxResults) {
|
protected Map<String, LDAPUser> searchLDAP(Map<String, String> attributes, int maxResults) {
|
||||||
IdentityManager identityManager = getIdentityManager();
|
|
||||||
Map<String, User> results = new HashMap<String, User>();
|
Map<String, LDAPUser> results = new HashMap<String, LDAPUser>();
|
||||||
if (attributes.containsKey(USERNAME)) {
|
if (attributes.containsKey(USERNAME)) {
|
||||||
User user = BasicModel.getUser(identityManager, attributes.get(USERNAME));
|
LDAPUser user = LDAPUtils.getUser(this.ldapIdentityStore, attributes.get(USERNAME));
|
||||||
if (user != null) {
|
if (user != null) {
|
||||||
results.put(user.getLoginName(), user);
|
results.put(user.getLoginName(), user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attributes.containsKey(EMAIL)) {
|
if (attributes.containsKey(EMAIL)) {
|
||||||
User user = queryByEmail(identityManager, attributes.get(EMAIL));
|
LDAPUser user = queryByEmail(attributes.get(EMAIL));
|
||||||
if (user != null) {
|
if (user != null) {
|
||||||
results.put(user.getLoginName(), user);
|
results.put(user.getLoginName(), user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attributes.containsKey(FIRST_NAME) || attributes.containsKey(LAST_NAME)) {
|
if (attributes.containsKey(FIRST_NAME) || attributes.containsKey(LAST_NAME)) {
|
||||||
IdentityQuery<User> query = identityManager.createIdentityQuery(User.class);
|
IdentityQueryBuilder queryBuilder = this.ldapIdentityStore.createQueryBuilder();
|
||||||
|
IdentityQuery<LDAPUser> query = queryBuilder.createIdentityQuery(LDAPUser.class);
|
||||||
if (attributes.containsKey(FIRST_NAME)) {
|
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)) {
|
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);
|
query.setLimit(maxResults);
|
||||||
List<User> agents = query.getResultList();
|
List<LDAPUser> users = query.getResultList();
|
||||||
for (User user : agents) {
|
for (LDAPUser user : users) {
|
||||||
results.put(user.getLoginName(), user);
|
results.put(user.getLoginName(), user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -211,85 +188,69 @@ public class LDAPFederationProvider implements UserFederationProvider {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isValid(UserModel local) {
|
public boolean isValid(UserModel local) {
|
||||||
try {
|
LDAPUser ldapUser = LDAPUtils.getUser(this.ldapIdentityStore, local.getUsername());
|
||||||
User picketlinkUser = LDAPUtils.getUser(partitionManager, local.getUsername());
|
if (ldapUser == null) {
|
||||||
if (picketlinkUser == null) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return picketlinkUser.getId().equals(local.getAttribute(LDAP_ID));
|
return ldapUser.getId().equals(local.getAttribute(LDAPConstants.LDAP_ID));
|
||||||
} catch (IdentityManagementException ie) {
|
|
||||||
throw convertIDMException(ie);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UserModel getUserByUsername(RealmModel realm, String username) {
|
public UserModel getUserByUsername(RealmModel realm, String username) {
|
||||||
try {
|
LDAPUser ldapUser = LDAPUtils.getUser(this.ldapIdentityStore, username);
|
||||||
User picketlinkUser = LDAPUtils.getUser(partitionManager, username);
|
if (ldapUser == null) {
|
||||||
if (picketlinkUser == null) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// KEYCLOAK-808: Should we allow case-sensitivity to be configurable?
|
// KEYCLOAK-808: Should we allow case-sensitivity to be configurable?
|
||||||
if (!username.equals(picketlinkUser.getLoginName())) {
|
if (!username.equals(ldapUser.getLoginName())) {
|
||||||
logger.warnf("User found in LDAP but with different username. LDAP username: %s, Searched username: %s", username, picketlinkUser.getLoginName());
|
logger.warnf("User found in LDAP but with different username. LDAP username: %s, Searched username: %s", username, ldapUser.getLoginName());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return importUserFromPicketlink(realm, picketlinkUser);
|
return importUserFromLDAP(realm, ldapUser);
|
||||||
} catch (IdentityManagementException ie) {
|
|
||||||
throw convertIDMException(ie);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public IdentityManager getIdentityManager() {
|
protected UserModel importUserFromLDAP(RealmModel realm, LDAPUser ldapUser) {
|
||||||
return partitionManager.createIdentityManager();
|
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());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected UserModel importUserFromPicketlink(RealmModel realm, User picketlinkUser) {
|
UserModel imported = session.userStorage().addUser(realm, ldapUser.getLoginName());
|
||||||
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());
|
|
||||||
}
|
|
||||||
|
|
||||||
UserModel imported = session.userStorage().addUser(realm, picketlinkUser.getLoginName());
|
|
||||||
imported.setEnabled(true);
|
imported.setEnabled(true);
|
||||||
imported.setEmail(email);
|
imported.setEmail(email);
|
||||||
imported.setFirstName(picketlinkUser.getFirstName());
|
imported.setFirstName(ldapUser.getFirstName());
|
||||||
imported.setLastName(picketlinkUser.getLastName());
|
imported.setLastName(ldapUser.getLastName());
|
||||||
imported.setFederationLink(model.getId());
|
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);
|
return proxy(imported);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected User queryByEmail(IdentityManager identityManager, String email) throws IdentityManagementException {
|
protected LDAPUser queryByEmail(String email) {
|
||||||
return LDAPUtils.getUserByEmail(identityManager, email);
|
return LDAPUtils.getUserByEmail(this.ldapIdentityStore, email);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UserModel getUserByEmail(RealmModel realm, String email) {
|
public UserModel getUserByEmail(RealmModel realm, String email) {
|
||||||
IdentityManager identityManager = getIdentityManager();
|
LDAPUser ldapUser = queryByEmail(email);
|
||||||
|
if (ldapUser == null) {
|
||||||
try {
|
|
||||||
User picketlinkUser = queryByEmail(identityManager, email);
|
|
||||||
if (picketlinkUser == null) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// KEYCLOAK-808: Should we allow case-sensitivity to be configurable?
|
// KEYCLOAK-808: Should we allow case-sensitivity to be configurable?
|
||||||
if (!email.equals(picketlinkUser.getEmail())) {
|
if (!email.equals(ldapUser.getEmail())) {
|
||||||
logger.warnf("User found in LDAP but with different email. LDAP email: %s, Searched email: %s", email, picketlinkUser.getEmail());
|
logger.warnf("User found in LDAP but with different email. LDAP email: %s, Searched email: %s", email, ldapUser.getEmail());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return importUserFromPicketlink(realm, picketlinkUser);
|
return importUserFromLDAP(realm, ldapUser);
|
||||||
} catch (IdentityManagementException ie) {
|
|
||||||
throw convertIDMException(ie);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -302,18 +263,14 @@ public class LDAPFederationProvider implements UserFederationProvider {
|
||||||
// complete I don't think we have to do anything here
|
// 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()) {
|
if (kerberosConfig.isAllowKerberosAuthentication() && kerberosConfig.isUseKerberosForPasswordAuthentication()) {
|
||||||
// Use Kerberos JAAS (Krb5LoginModule)
|
// Use Kerberos JAAS (Krb5LoginModule)
|
||||||
KerberosUsernamePasswordAuthenticator authenticator = factory.createKerberosUsernamePasswordAuthenticator(kerberosConfig);
|
KerberosUsernamePasswordAuthenticator authenticator = factory.createKerberosUsernamePasswordAuthenticator(kerberosConfig);
|
||||||
return authenticator.validUser(username, password);
|
return authenticator.validUser(user.getUsername(), password);
|
||||||
} else {
|
} else {
|
||||||
// Use Naming LDAP API
|
// Use Naming LDAP API
|
||||||
try {
|
return LDAPUtils.validatePassword(this.ldapIdentityStore, user, password);
|
||||||
return LDAPUtils.validatePassword(partitionManager, username, password);
|
|
||||||
} catch (IdentityManagementException ie) {
|
|
||||||
throw convertIDMException(ie);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -322,7 +279,7 @@ public class LDAPFederationProvider implements UserFederationProvider {
|
||||||
public boolean validCredentials(RealmModel realm, UserModel user, List<UserCredentialModel> input) {
|
public boolean validCredentials(RealmModel realm, UserModel user, List<UserCredentialModel> input) {
|
||||||
for (UserCredentialModel cred : input) {
|
for (UserCredentialModel cred : input) {
|
||||||
if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
|
if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
|
||||||
return validPassword(user.getUsername(), cred.getValue());
|
return validPassword(user, cred.getValue());
|
||||||
} else {
|
} else {
|
||||||
return false; // invalid cred type
|
return false; // invalid cred type
|
||||||
}
|
}
|
||||||
|
@ -353,7 +310,7 @@ public class LDAPFederationProvider implements UserFederationProvider {
|
||||||
UserModel user = findOrCreateAuthenticatedUser(realm, username);
|
UserModel user = findOrCreateAuthenticatedUser(realm, username);
|
||||||
|
|
||||||
if (user == null) {
|
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();
|
return CredentialValidationOutput.failed();
|
||||||
} else {
|
} else {
|
||||||
String delegationCredential = spnegoAuthenticator.getSerializedDelegationCredential();
|
String delegationCredential = spnegoAuthenticator.getSerializedDelegationCredential();
|
||||||
|
@ -375,24 +332,23 @@ public class LDAPFederationProvider implements UserFederationProvider {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {
|
||||||
//To change body of implemented methods use File | Settings | File Templates.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void importPicketlinkUsers(RealmModel realm, List<User> users, UserFederationProviderModel fedModel) {
|
protected void importLDAPUsers(RealmModel realm, List<LDAPUser> ldapUsers, UserFederationProviderModel fedModel) {
|
||||||
for (User picketlinkUser : users) {
|
for (LDAPUser ldapUser : ldapUsers) {
|
||||||
String username = picketlinkUser.getLoginName();
|
String username = ldapUser.getLoginName();
|
||||||
UserModel currentUser = session.userStorage().getUserByUsername(username, realm);
|
UserModel currentUser = session.userStorage().getUserByUsername(username, realm);
|
||||||
|
|
||||||
if (currentUser == null) {
|
if (currentUser == null) {
|
||||||
// Add new user to Keycloak
|
// Add new user to Keycloak
|
||||||
importUserFromPicketlink(realm, picketlinkUser);
|
importUserFromLDAP(realm, ldapUser);
|
||||||
} else {
|
} 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
|
// 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.setEmail(email);
|
||||||
currentUser.setFirstName(picketlinkUser.getFirstName());
|
currentUser.setFirstName(ldapUser.getFirstName());
|
||||||
currentUser.setLastName(picketlinkUser.getLastName());
|
currentUser.setLastName(ldapUser.getLastName());
|
||||||
logger.debugf("Updated user from LDAP: %s", currentUser.getUsername());
|
logger.debugf("Updated user from LDAP: %s", currentUser.getUsername());
|
||||||
} else {
|
} else {
|
||||||
logger.warnf("User '%s' is not updated during sync as he is not linked to federation provider '%s'", username, fedModel.getDisplayName());
|
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
|
* Called after successful kerberos authentication
|
||||||
*
|
*
|
||||||
* @param realm
|
* @param realm realm
|
||||||
* @param username username without realm prefix
|
* @param username username without realm prefix
|
||||||
* @return
|
* @return finded or newly created user
|
||||||
*/
|
*/
|
||||||
protected UserModel findOrCreateAuthenticatedUser(RealmModel realm, String username) {
|
protected UserModel findOrCreateAuthenticatedUser(RealmModel realm, String username) {
|
||||||
UserModel user = session.userStorage().getUserByUsername(username, realm);
|
UserModel user = session.userStorage().getUserByUsername(username, realm);
|
||||||
if (user != null) {
|
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())) {
|
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;
|
return null;
|
||||||
} else if (isValid(user)) {
|
} else if (isValid(user)) {
|
||||||
return proxy(user);
|
return proxy(user);
|
||||||
} else {
|
} else {
|
||||||
logger.warn("User with username " + username + " already exists and is linked to provider [" + model.getDisplayName() +
|
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",
|
||||||
"] but is not valid. Stale LDAP_ID on local user is: " + user.getAttribute(LDAP_ID));
|
username, model.getDisplayName(), user.getAttribute(LDAPConstants.LDAP_ID));
|
||||||
logger.warn("Will re-create user");
|
logger.warn("Will re-create user");
|
||||||
session.userStorage().removeUser(realm, user);
|
session.userStorage().removeUser(realm, user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creating user to local storage
|
// 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);
|
return getUserByUsername(realm, username);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,10 +3,15 @@ package org.keycloak.federation.ldap;
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.keycloak.Config;
|
import org.keycloak.Config;
|
||||||
import org.keycloak.federation.kerberos.CommonKerberosConfig;
|
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.KerberosServerSubjectAuthenticator;
|
||||||
import org.keycloak.federation.kerberos.impl.KerberosUsernamePasswordAuthenticator;
|
import org.keycloak.federation.kerberos.impl.KerberosUsernamePasswordAuthenticator;
|
||||||
import org.keycloak.federation.kerberos.impl.SPNEGOAuthenticator;
|
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.KeycloakSession;
|
||||||
import org.keycloak.models.KeycloakSessionFactory;
|
import org.keycloak.models.KeycloakSessionFactory;
|
||||||
import org.keycloak.models.KeycloakSessionTask;
|
import org.keycloak.models.KeycloakSessionTask;
|
||||||
|
@ -16,16 +21,6 @@ import org.keycloak.models.UserFederationProvider;
|
||||||
import org.keycloak.models.UserFederationProviderFactory;
|
import org.keycloak.models.UserFederationProviderFactory;
|
||||||
import org.keycloak.models.UserFederationProviderModel;
|
import org.keycloak.models.UserFederationProviderModel;
|
||||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
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.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
@ -41,6 +36,8 @@ public class LDAPFederationProviderFactory implements UserFederationProviderFact
|
||||||
private static final Logger logger = Logger.getLogger(LDAPFederationProviderFactory.class);
|
private static final Logger logger = Logger.getLogger(LDAPFederationProviderFactory.class);
|
||||||
public static final String PROVIDER_NAME = "ldap";
|
public static final String PROVIDER_NAME = "ldap";
|
||||||
|
|
||||||
|
private LDAPIdentityStoreRegistry ldapStoreRegistry;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UserFederationProvider create(KeycloakSession session) {
|
public UserFederationProvider create(KeycloakSession session) {
|
||||||
throw new IllegalAccessError("Illegal to call this method");
|
throw new IllegalAccessError("Illegal to call this method");
|
||||||
|
@ -48,13 +45,13 @@ public class LDAPFederationProviderFactory implements UserFederationProviderFact
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LDAPFederationProvider getInstance(KeycloakSession session, UserFederationProviderModel model) {
|
public LDAPFederationProvider getInstance(KeycloakSession session, UserFederationProviderModel model) {
|
||||||
PartitionManagerProvider idmProvider = session.getProvider(PartitionManagerProvider.class);
|
LDAPIdentityStore ldapIdentityStore = this.ldapStoreRegistry.getLdapStore(model);
|
||||||
PartitionManager partition = idmProvider.getPartitionManager(model);
|
return new LDAPFederationProvider(this, session, model, ldapIdentityStore);
|
||||||
return new LDAPFederationProvider(this, session, model, partition);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(Config.Scope config) {
|
public void init(Config.Scope config) {
|
||||||
|
this.ldapStoreRegistry = new LDAPIdentityStoreRegistry();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -64,7 +61,7 @@ public class LDAPFederationProviderFactory implements UserFederationProviderFact
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {
|
||||||
|
this.ldapStoreRegistry = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -81,9 +78,8 @@ public class LDAPFederationProviderFactory implements UserFederationProviderFact
|
||||||
public void syncAllUsers(KeycloakSessionFactory sessionFactory, String realmId, UserFederationProviderModel model) {
|
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());
|
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);
|
LDAPIdentityStore ldapIdentityStore = this.ldapStoreRegistry.getLdapStore(model);
|
||||||
PartitionManager partitionMgr = idmProvider.getPartitionManager(model);
|
IdentityQuery<LDAPUser> userQuery = ldapIdentityStore.createQueryBuilder().createIdentityQuery(LDAPUser.class);
|
||||||
IdentityQuery<User> userQuery = partitionMgr.createIdentityManager().createIdentityQuery(User.class);
|
|
||||||
syncImpl(sessionFactory, userQuery, realmId, model);
|
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?
|
// 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
|
@Override
|
||||||
public void syncChangedUsers(KeycloakSessionFactory sessionFactory, String realmId, UserFederationProviderModel model, Date lastSync) {
|
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);
|
LDAPIdentityStore ldapIdentityStore = this.ldapStoreRegistry.getLdapStore(model);
|
||||||
PartitionManager partitionMgr = idmProvider.getPartitionManager(model);
|
|
||||||
|
|
||||||
// Sync newly created users
|
// Sync newly created users
|
||||||
IdentityManager identityManager = partitionMgr.createIdentityManager();
|
IdentityQueryBuilder queryBuilder = ldapIdentityStore.createQueryBuilder();
|
||||||
IdentityQueryBuilder queryBuilder = identityManager.getQueryBuilder();
|
|
||||||
Condition condition = queryBuilder.greaterThanOrEqualTo(IdentityType.CREATED_DATE, lastSync);
|
Condition condition = queryBuilder.greaterThanOrEqualTo(IdentityType.CREATED_DATE, lastSync);
|
||||||
IdentityQuery<User> userQuery = queryBuilder.createIdentityQuery(User.class).where(condition);
|
IdentityQuery<LDAPUser> userQuery = queryBuilder.createIdentityQuery(LDAPUser.class).where(condition);
|
||||||
syncImpl(sessionFactory, userQuery, realmId, model);
|
syncImpl(sessionFactory, userQuery, realmId, model);
|
||||||
|
|
||||||
// Sync updated users
|
// Sync updated users
|
||||||
queryBuilder = identityManager.getQueryBuilder();
|
|
||||||
condition = queryBuilder.greaterThanOrEqualTo(LDAPUtils.MODIFY_DATE, lastSync);
|
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);
|
syncImpl(sessionFactory, userQuery, realmId, model);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void syncImpl(KeycloakSessionFactory sessionFactory, IdentityQuery<User> userQuery, final String realmId, final UserFederationProviderModel fedModel) {
|
protected void syncImpl(KeycloakSessionFactory sessionFactory, IdentityQuery<LDAPUser> userQuery, final String realmId, final UserFederationProviderModel fedModel) {
|
||||||
boolean pagination = Boolean.parseBoolean(fedModel.getConfig().get(LDAPConstants.PAGINATION));
|
boolean pagination = Boolean.parseBoolean(fedModel.getConfig().get(LDAPConstants.PAGINATION));
|
||||||
|
|
||||||
if (pagination) {
|
if (pagination) {
|
||||||
|
@ -119,36 +112,36 @@ public class LDAPFederationProviderFactory implements UserFederationProviderFact
|
||||||
boolean nextPage = true;
|
boolean nextPage = true;
|
||||||
while (nextPage) {
|
while (nextPage) {
|
||||||
userQuery.setLimit(pageSize);
|
userQuery.setLimit(pageSize);
|
||||||
final List<User> users = userQuery.getResultList();
|
final List<LDAPUser> users = userQuery.getResultList();
|
||||||
nextPage = userQuery.getPaginationContext() != null;
|
nextPage = userQuery.getPaginationContext() != null;
|
||||||
|
|
||||||
KeycloakModelUtils.runJobInTransaction(sessionFactory, new KeycloakSessionTask() {
|
KeycloakModelUtils.runJobInTransaction(sessionFactory, new KeycloakSessionTask() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run(KeycloakSession session) {
|
public void run(KeycloakSession session) {
|
||||||
importPicketlinkUsers(session, realmId, fedModel, users);
|
importLdapUsers(session, realmId, fedModel, users);
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// LDAP pagination not available. Do everything in single transaction
|
// LDAP pagination not available. Do everything in single transaction
|
||||||
final List<User> users = userQuery.getResultList();
|
final List<LDAPUser> users = userQuery.getResultList();
|
||||||
KeycloakModelUtils.runJobInTransaction(sessionFactory, new KeycloakSessionTask() {
|
KeycloakModelUtils.runJobInTransaction(sessionFactory, new KeycloakSessionTask() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run(KeycloakSession session) {
|
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<User> users) {
|
protected void importLdapUsers(KeycloakSession session, String realmId, UserFederationProviderModel fedModel, List<LDAPUser> ldapUsers) {
|
||||||
RealmModel realm = session.realms().getRealm(realmId);
|
RealmModel realm = session.realms().getRealm(realmId);
|
||||||
LDAPFederationProvider ldapFedProvider = getInstance(session, fedModel);
|
LDAPFederationProvider ldapFedProvider = getInstance(session, fedModel);
|
||||||
ldapFedProvider.importPicketlinkUsers(realm, users, fedModel);
|
ldapFedProvider.importLDAPUsers(realm, ldapUsers, fedModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected SPNEGOAuthenticator createSPNEGOAuthenticator(String spnegoToken, CommonKerberosConfig kerberosConfig) {
|
protected SPNEGOAuthenticator createSPNEGOAuthenticator(String spnegoToken, CommonKerberosConfig kerberosConfig) {
|
||||||
|
|
|
@ -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 <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
|
*/
|
||||||
|
public class LDAPIdentityStoreRegistry {
|
||||||
|
|
||||||
|
private static final Logger logger = Logger.getLogger(LDAPIdentityStoreRegistry.class);
|
||||||
|
|
||||||
|
private Map<String, LDAPIdentityStoreContext> ldapStores = new ConcurrentHashMap<String, LDAPIdentityStoreContext>();
|
||||||
|
|
||||||
|
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<String, String> 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<String, String> ldapConfig) {
|
||||||
|
Map<String, String> copy = new HashMap<String, String>(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<String,String> 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<String>(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<String,String> 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<objectClasses.length ; i++) {
|
||||||
|
userObjectClasses[i] = objectClasses[i].trim();
|
||||||
|
}
|
||||||
|
return userObjectClasses;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class LDAPIdentityStoreContext {
|
||||||
|
|
||||||
|
private LDAPIdentityStoreContext(Map<String,String> config, LDAPIdentityStore store) {
|
||||||
|
this.config = config;
|
||||||
|
this.store = store;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String,String> config;
|
||||||
|
private LDAPIdentityStore store;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,22 +1,21 @@
|
||||||
package org.keycloak.federation.ldap;
|
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.keycloak.models.ModelDuplicateException;
|
||||||
import org.picketlink.idm.IdentityManagementException;
|
import org.keycloak.models.UserModel;
|
||||||
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 java.util.List;
|
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 <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
|
@ -24,99 +23,102 @@ public class LDAPUtils {
|
||||||
|
|
||||||
public static QueryParameter MODIFY_DATE = new AttributeParameter("modifyDate");
|
public static QueryParameter MODIFY_DATE = new AttributeParameter("modifyDate");
|
||||||
|
|
||||||
public static User addUser(PartitionManager partitionManager, String username, String firstName, String lastName, String email) {
|
public static LDAPUser addUser(LDAPIdentityStore ldapIdentityStore, String username, String firstName, String lastName, String email) {
|
||||||
IdentityManager identityManager = getIdentityManager(partitionManager);
|
if (getUser(ldapIdentityStore, username) != null) {
|
||||||
|
|
||||||
if (BasicModel.getUser(identityManager, username) != null) {
|
|
||||||
throw new ModelDuplicateException("User with same username already exists");
|
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");
|
throw new ModelDuplicateException("User with same email already exists");
|
||||||
}
|
}
|
||||||
|
|
||||||
User picketlinkUser = new User(username);
|
LDAPUser ldapUser = new LDAPUser(username);
|
||||||
picketlinkUser.setFirstName(firstName);
|
ldapUser.setFirstName(firstName);
|
||||||
picketlinkUser.setLastName(lastName);
|
ldapUser.setLastName(lastName);
|
||||||
picketlinkUser.setEmail(email);
|
ldapUser.setEmail(email);
|
||||||
picketlinkUser.setAttribute(new Attribute("fullName", getFullName(username, firstName, lastName)));
|
ldapUser.setAttribute(new Attribute<String>("fullName", getFullName(username, firstName, lastName)));
|
||||||
identityManager.add(picketlinkUser);
|
ldapIdentityStore.add(ldapUser);
|
||||||
return picketlinkUser;
|
return ldapUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static User updateUser(PartitionManager partitionManager, String username, String firstName, String lastName, String email) {
|
public static LDAPUser updateUser(LDAPIdentityStore ldapIdentityStore, String username, String firstName, String lastName, String email) {
|
||||||
IdentityManager idmManager = getIdentityManager(partitionManager);
|
LDAPUser ldapUser = getUser(ldapIdentityStore, username);
|
||||||
User picketlinkUser = BasicModel.getUser(idmManager, username);
|
ldapUser.setFirstName(firstName);
|
||||||
picketlinkUser.setFirstName(firstName);
|
ldapUser.setLastName(lastName);
|
||||||
picketlinkUser.setLastName(lastName);
|
ldapUser.setEmail(email);
|
||||||
picketlinkUser.setEmail(email);
|
ldapIdentityStore.update(ldapUser);
|
||||||
idmManager.update(picketlinkUser);
|
return ldapUser;
|
||||||
return picketlinkUser;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void updatePassword(PartitionManager partitionManager, User picketlinkUser, String password) {
|
public static void updatePassword(LDAPIdentityStore ldapIdentityStore, UserModel user, String password) {
|
||||||
IdentityManager idmManager = getIdentityManager(partitionManager);
|
LDAPUser ldapUser = convertUserForPasswordUpdate(user);
|
||||||
idmManager.updateCredential(picketlinkUser, new Password(password.toCharArray()));
|
|
||||||
|
ldapIdentityStore.updatePassword(ldapUser, password);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean validatePassword(PartitionManager partitionManager, String username, String password) {
|
public static void updatePassword(LDAPIdentityStore ldapIdentityStore, LDAPUser user, String password) {
|
||||||
IdentityManager idmManager = getIdentityManager(partitionManager);
|
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 User getUser(PartitionManager partitionManager, String username) {
|
public static boolean validatePassword(LDAPIdentityStore ldapIdentityStore, UserModel user, String password) {
|
||||||
IdentityManager idmManager = getIdentityManager(partitionManager);
|
LDAPUser ldapUser = convertUserForPasswordUpdate(user);
|
||||||
return BasicModel.getUser(idmManager, username);
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
return ldapUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static User getUserByEmail(IdentityManager idmManager, String email) throws IdentityManagementException {
|
public static LDAPUser getUserByEmail(LDAPIdentityStore ldapIdentityStore, String email) {
|
||||||
List<User> agents = idmManager.createIdentityQuery(User.class)
|
IdentityQueryBuilder queryBuilder = ldapIdentityStore.createQueryBuilder();
|
||||||
.setParameter(User.EMAIL, email).getResultList();
|
IdentityQuery<LDAPUser> query = queryBuilder.createIdentityQuery(LDAPUser.class)
|
||||||
|
.where(queryBuilder.equal(LDAPUser.EMAIL, email));
|
||||||
|
List<LDAPUser> users = query.getResultList();
|
||||||
|
|
||||||
if (agents.isEmpty()) {
|
if (users.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
} else if (agents.size() == 1) {
|
} else if (users.size() == 1) {
|
||||||
return agents.get(0);
|
return users.get(0);
|
||||||
} else {
|
} 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) {
|
public static boolean removeUser(LDAPIdentityStore ldapIdentityStore, String username) {
|
||||||
IdentityManager idmManager = getIdentityManager(partitionManager);
|
LDAPUser ldapUser = getUser(ldapIdentityStore, username);
|
||||||
User picketlinkUser = BasicModel.getUser(idmManager, username);
|
if (ldapUser == null) {
|
||||||
if (picketlinkUser == null) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
idmManager.remove(picketlinkUser);
|
ldapIdentityStore.remove(ldapUser);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void removeAllUsers(PartitionManager partitionManager) {
|
public static void removeAllUsers(LDAPIdentityStore ldapIdentityStore) {
|
||||||
IdentityManager idmManager = getIdentityManager(partitionManager);
|
List<LDAPUser> allUsers = getAllUsers(ldapIdentityStore);
|
||||||
List<User> users = idmManager.createIdentityQuery(User.class).getResultList();
|
|
||||||
|
|
||||||
for (User user : users) {
|
for (LDAPUser user : allUsers) {
|
||||||
idmManager.remove(user);
|
ldapIdentityStore.remove(user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<User> getAllUsers(PartitionManager partitionManager) {
|
public static List<LDAPUser> getAllUsers(LDAPIdentityStore ldapIdentityStore) {
|
||||||
IdentityManager idmManager = getIdentityManager(partitionManager);
|
IdentityQuery<LDAPUser> userQuery = ldapIdentityStore.createQueryBuilder().createIdentityQuery(LDAPUser.class);
|
||||||
return idmManager.createIdentityQuery(User.class).getResultList();
|
return userQuery.getResultList();
|
||||||
}
|
|
||||||
|
|
||||||
private static IdentityManager getIdentityManager(PartitionManager partitionManager) {
|
|
||||||
return partitionManager.createIdentityManager();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Needed for ActiveDirectory updates
|
// Needed for ActiveDirectory updates
|
||||||
|
|
|
@ -1,16 +1,11 @@
|
||||||
package org.keycloak.federation.ldap;
|
package org.keycloak.federation.ldap;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
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.UserCredentialModel;
|
||||||
import org.keycloak.models.UserModel;
|
import org.keycloak.models.UserModel;
|
||||||
import org.keycloak.models.utils.UserModelDelegate;
|
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 <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
@ -28,52 +23,43 @@ public class WritableLDAPUserModelDelegate extends UserModelDelegate implements
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setUsername(String username) {
|
public void setUsername(String username) {
|
||||||
IdentityManager identityManager = provider.getIdentityManager();
|
LDAPIdentityStore ldapIdentityStore = provider.getLdapIdentityStore();
|
||||||
|
|
||||||
try {
|
LDAPUser ldapUser = LDAPUtils.getUser(ldapIdentityStore, delegate.getUsername());
|
||||||
User picketlinkUser = BasicModel.getUser(identityManager, delegate.getUsername());
|
if (ldapUser == null) {
|
||||||
if (picketlinkUser == null) {
|
|
||||||
throw new IllegalStateException("User not found in LDAP storage!");
|
throw new IllegalStateException("User not found in LDAP storage!");
|
||||||
}
|
}
|
||||||
picketlinkUser.setLoginName(username);
|
ldapUser.setLoginName(username);
|
||||||
identityManager.update(picketlinkUser);
|
ldapIdentityStore.update(ldapUser);
|
||||||
} catch (IdentityManagementException ie) {
|
|
||||||
throw new ModelException(ie);
|
|
||||||
}
|
|
||||||
delegate.setUsername(username);
|
delegate.setUsername(username);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setLastName(String lastName) {
|
public void setLastName(String lastName) {
|
||||||
IdentityManager identityManager = provider.getIdentityManager();
|
LDAPIdentityStore ldapIdentityStore = provider.getLdapIdentityStore();
|
||||||
|
|
||||||
try {
|
LDAPUser ldapUser = LDAPUtils.getUser(ldapIdentityStore, delegate.getUsername());
|
||||||
User picketlinkUser = BasicModel.getUser(identityManager, delegate.getUsername());
|
if (ldapUser == null) {
|
||||||
if (picketlinkUser == null) {
|
|
||||||
throw new IllegalStateException("User not found in LDAP storage!");
|
throw new IllegalStateException("User not found in LDAP storage!");
|
||||||
}
|
}
|
||||||
picketlinkUser.setLastName(lastName);
|
ldapUser.setLastName(lastName);
|
||||||
identityManager.update(picketlinkUser);
|
ldapIdentityStore.update(ldapUser);
|
||||||
} catch (IdentityManagementException ie) {
|
|
||||||
throw new ModelException(ie);
|
|
||||||
}
|
|
||||||
delegate.setLastName(lastName);
|
delegate.setLastName(lastName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setFirstName(String first) {
|
public void setFirstName(String first) {
|
||||||
IdentityManager identityManager = provider.getIdentityManager();
|
LDAPIdentityStore ldapIdentityStore = provider.getLdapIdentityStore();
|
||||||
|
|
||||||
try {
|
LDAPUser ldapUser = LDAPUtils.getUser(ldapIdentityStore, delegate.getUsername());
|
||||||
User picketlinkUser = BasicModel.getUser(identityManager, delegate.getUsername());
|
if (ldapUser == null) {
|
||||||
if (picketlinkUser == null) {
|
|
||||||
throw new IllegalStateException("User not found in LDAP storage!");
|
throw new IllegalStateException("User not found in LDAP storage!");
|
||||||
}
|
}
|
||||||
picketlinkUser.setFirstName(first);
|
ldapUser.setFirstName(first);
|
||||||
identityManager.update(picketlinkUser);
|
ldapIdentityStore.update(ldapUser);
|
||||||
} catch (IdentityManagementException ie) {
|
|
||||||
throw new ModelException(ie);
|
|
||||||
}
|
|
||||||
delegate.setFirstName(first);
|
delegate.setFirstName(first);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,41 +69,31 @@ public class WritableLDAPUserModelDelegate extends UserModelDelegate implements
|
||||||
delegate.updateCredential(cred);
|
delegate.updateCredential(cred);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
IdentityManager identityManager = provider.getIdentityManager();
|
|
||||||
|
|
||||||
try {
|
LDAPIdentityStore ldapIdentityStore = provider.getLdapIdentityStore();
|
||||||
User picketlinkUser = BasicModel.getUser(identityManager, getUsername());
|
LDAPUser ldapUser = LDAPUtils.getUser(ldapIdentityStore, delegate.getUsername());
|
||||||
if (picketlinkUser == null) {
|
if (ldapUser == null) {
|
||||||
logger.debugf("User '%s' doesn't exists. Skip password update", getUsername());
|
throw new IllegalStateException("User " + delegate.getUsername() + " not found in LDAP storage!");
|
||||||
throw new IllegalStateException("User doesn't exist in LDAP storage");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
|
if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
|
||||||
identityManager.updateCredential(picketlinkUser, new Password(cred.getValue().toCharArray()));
|
LDAPUtils.updatePassword(ldapIdentityStore, delegate, cred.getValue());
|
||||||
} else if (cred.getType().equals(UserCredentialModel.TOTP)) {
|
} else {
|
||||||
TOTPCredential credential = new TOTPCredential(cred.getValue());
|
logger.warnf("Don't know how to update credential of type [%s] for user [%s]", cred.getType(), delegate.getUsername());
|
||||||
credential.setDevice(cred.getDevice());
|
|
||||||
identityManager.updateCredential(picketlinkUser, credential);
|
|
||||||
}
|
}
|
||||||
} catch (IdentityManagementException ie) {
|
|
||||||
throw new ModelException(ie);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setEmail(String email) {
|
public void setEmail(String email) {
|
||||||
IdentityManager identityManager = provider.getIdentityManager();
|
LDAPIdentityStore ldapIdentityStore = provider.getLdapIdentityStore();
|
||||||
|
|
||||||
try {
|
LDAPUser ldapUser = LDAPUtils.getUser(ldapIdentityStore, delegate.getUsername());
|
||||||
User picketlinkUser = BasicModel.getUser(identityManager, delegate.getUsername());
|
if (ldapUser == null) {
|
||||||
if (picketlinkUser == null) {
|
|
||||||
throw new IllegalStateException("User not found in LDAP storage!");
|
throw new IllegalStateException("User not found in LDAP storage!");
|
||||||
}
|
}
|
||||||
picketlinkUser.setEmail(email);
|
ldapUser.setEmail(email);
|
||||||
identityManager.update(picketlinkUser);
|
ldapIdentityStore.update(ldapUser);
|
||||||
} catch (IdentityManagementException ie) {
|
|
||||||
throw new ModelException(ie);
|
|
||||||
}
|
|
||||||
delegate.setEmail(email);
|
delegate.setEmail(email);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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<String, Attribute<? extends Serializable>> attributes =
|
||||||
|
new HashMap<String, Attribute<? extends Serializable>>();
|
||||||
|
|
||||||
|
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<? extends Serializable> attribute) {
|
||||||
|
attributes.put(attribute.getName(), attribute);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeAttribute(String name) {
|
||||||
|
attributes.remove(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <T extends Serializable> Attribute<T> getAttribute(String name) {
|
||||||
|
return (Attribute<T>) attributes.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<Attribute<? extends Serializable>> getAttributes() {
|
||||||
|
return unmodifiableCollection(attributes.values());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String,Attribute<? extends Serializable>> 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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 <T>
|
||||||
|
*/
|
||||||
|
public class Attribute<T extends Serializable> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Managed properties are stored as ad-hoc attributes and mapped from and to a specific property of a type.</p>
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
boolean managed() default false;
|
||||||
|
|
||||||
|
}
|
|
@ -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<? extends Serializable> 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
|
||||||
|
*/
|
||||||
|
<T extends Serializable> Attribute<T> getAttribute(String name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a Map containing all attribute values for this IdentityType instance.
|
||||||
|
*
|
||||||
|
* @return map of attribute names and their values
|
||||||
|
*/
|
||||||
|
Collection<Attribute<? extends Serializable>> getAttributes();
|
||||||
|
|
||||||
|
public final class QUERY_ATTRIBUTE {
|
||||||
|
public static AttributeParameter byName(String name) {
|
||||||
|
return new AttributeParameter(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Sets the current enabled status of this {@link IdentityType}.</p>
|
||||||
|
*
|
||||||
|
* @param enabled
|
||||||
|
*/
|
||||||
|
void setEnabled(boolean enabled);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the date that this IdentityType instance was created.
|
||||||
|
*
|
||||||
|
* @return Date value representing the creation date
|
||||||
|
*/
|
||||||
|
Date getCreatedDate();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Sets the date that this {@link IdentityType} was created.</p>
|
||||||
|
*
|
||||||
|
* @param createdDate
|
||||||
|
*/
|
||||||
|
void setCreatedDate(Date createdDate);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the date that this IdentityType expires, or null if there is no expiry date.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Date getExpirationDate();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Sets the date that this {@link IdentityType} expires.</p>
|
||||||
|
*
|
||||||
|
* @param expirationDate
|
||||||
|
*/
|
||||||
|
void setExpirationDate(Date expirationDate);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
package org.keycloak.federation.ldap.idm.query;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>This class can be used to define a query parameter for properties annotated with
|
||||||
|
* {@link org.keycloak.federation.ldap.idm.model.AttributeProperty}.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author pedroigor
|
||||||
|
*/
|
||||||
|
public class AttributeParameter implements QueryParameter {
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
public AttributeParameter(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package org.keycloak.federation.ldap.idm.query;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>A {@link Condition} is used to specify how a specific {@link QueryParameter}
|
||||||
|
* is defined in order to filter query results.</p>
|
||||||
|
*
|
||||||
|
* @author Pedro Igor
|
||||||
|
*/
|
||||||
|
public interface Condition {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>The {@link QueryParameter} restricted by this condition.</p>
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
QueryParameter getParameter();
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>An {@link IdentityQuery} is responsible for querying the underlying identity stores for instances of
|
||||||
|
* a given {@link IdentityType}.</p>
|
||||||
|
*
|
||||||
|
* <p>Instances of this class are obtained using the {@link IdentityQueryBuilder#createIdentityQuery(Class)}
|
||||||
|
* method.</p>
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* 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<User> result = query.getResultList();
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* <p>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.</p>
|
||||||
|
*
|
||||||
|
* @author Shane Bryzak
|
||||||
|
* @author Pedro Igor
|
||||||
|
*/
|
||||||
|
public interface IdentityQuery<T extends IdentityType> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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<T> 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<T> 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<T> setSortAscending(boolean sortAscending);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Set a query parameter to this query in order to filter the results.</p>
|
||||||
|
*
|
||||||
|
* <p>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.</p>
|
||||||
|
*
|
||||||
|
* @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<T> setParameter(QueryParameter param, Object... value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Add to this query the conditions that will be used to filter results.</p>
|
||||||
|
*
|
||||||
|
* <p>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.</p>
|
||||||
|
*
|
||||||
|
* @param condition One or more conditions created from {@link IdentityQueryBuilder}.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
IdentityQuery<T> where(Condition... condition);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Add to this query the sorting conditions to be applied to the results.</p>
|
||||||
|
*
|
||||||
|
* @param sorts The ordering conditions.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
IdentityQuery<T> sortBy(Sort... sorts);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>The type used to create this query.</p>
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Class<T> getIdentityType();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Returns a map with all the parameter set for this query.</p>
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*
|
||||||
|
* @deprecated Use {@link IdentityQuery#getConditions()} instead. Will be removed.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
Map<QueryParameter, Object[]> getParameters();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Returns a set containing all conditions used by this query to filter its results.</p>
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Set<Condition> getConditions();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Returns a set containing all sorting conditions used to filter the results.</p>
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Set<Sort> getSorting();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Returns the value used to restrict the given query parameter.</p>
|
||||||
|
*
|
||||||
|
* @param queryParameter
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
Object[] getParameter(QueryParameter queryParameter);
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
Map<QueryParameter, Object[]> getParameters(Class<?> type);
|
||||||
|
|
||||||
|
int getOffset();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Set the position of the first result to retrieve.</p>
|
||||||
|
*
|
||||||
|
* @param offset
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
IdentityQuery<T> setOffset(int offset);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Returns the number of instances to retrieve.</p>
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
int getLimit();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Set the maximum number of results to retrieve.</p>
|
||||||
|
*
|
||||||
|
* @param limit the number of instances to retrieve.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
IdentityQuery<T> setLimit(int limit);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>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.</p>
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
List<T> 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();
|
||||||
|
}
|
|
@ -0,0 +1,124 @@
|
||||||
|
package org.keycloak.federation.ldap.idm.query;
|
||||||
|
|
||||||
|
import org.keycloak.federation.ldap.idm.model.IdentityType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>The {@link IdentityQueryBuilder} is responsible for creating {@link IdentityQuery} instances and also
|
||||||
|
* provide methods to create conditions, orderings, sorting, etc.</p>
|
||||||
|
*
|
||||||
|
* @author Pedro Igor
|
||||||
|
*/
|
||||||
|
public interface IdentityQueryBuilder {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Create a condition for testing the whether the query parameter satisfies the given pattern..</p>
|
||||||
|
*
|
||||||
|
* @param parameter The query parameter.
|
||||||
|
* @param pattern The pattern to match.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Condition like(QueryParameter parameter, String pattern);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Create a condition for testing the arguments for equality.</p>
|
||||||
|
*
|
||||||
|
* @param parameter The query parameter.
|
||||||
|
* @param value The value to compare.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Condition equal(QueryParameter parameter, Object value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Create a condition for testing whether the query parameter is grater than the given value..</p>
|
||||||
|
*
|
||||||
|
* @param parameter The query parameter.
|
||||||
|
* @param x The value to compare.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Condition greaterThan(QueryParameter parameter, Object x);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Create a condition for testing whether the query parameter is grater than or equal to the given value..</p>
|
||||||
|
*
|
||||||
|
* @param parameter The query parameter.
|
||||||
|
* @param x The value to compare.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Condition greaterThanOrEqualTo(QueryParameter parameter, Object x);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Create a condition for testing whether the query parameter is less than the given value..</p>
|
||||||
|
*
|
||||||
|
* @param parameter The query parameter.
|
||||||
|
* @param x The value to compare.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Condition lessThan(QueryParameter parameter, Object x);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Create a condition for testing whether the query parameter is less than or equal to the given value..</p>
|
||||||
|
*
|
||||||
|
* @param parameter The query parameter.
|
||||||
|
* @param x The value to compare.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Condition lessThanOrEqualTo(QueryParameter parameter, Object x);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Create a condition for testing whether the query parameter is between the given values.</p>
|
||||||
|
*
|
||||||
|
* @param parameter The query parameter.
|
||||||
|
* @param x The first value.
|
||||||
|
* @param x The second value.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Condition between(QueryParameter parameter, Object x, Object y);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Create a condition for testing whether the query parameter is contained in a list of values.</p>
|
||||||
|
*
|
||||||
|
* @param parameter The query parameter.
|
||||||
|
* @param values A list of values.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Condition in(QueryParameter parameter, Object... values);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Create an ascending order for the given <code>parameter</code>. Once created, you can use it to sort the results of a
|
||||||
|
* query.</p>
|
||||||
|
*
|
||||||
|
* @param parameter The query parameter to sort.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Sort asc(QueryParameter parameter);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Create an descending order for the given <code>parameter</code>. Once created, you can use it to sort the results of a
|
||||||
|
* query.</p>
|
||||||
|
*
|
||||||
|
* @param parameter The query parameter to sort.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Sort desc(QueryParameter parameter);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p> Create an {@link IdentityQuery} that can be used to query for {@link
|
||||||
|
* IdentityType} instances of a the given <code>identityType</code>. </p>
|
||||||
|
*
|
||||||
|
* @param identityType The type to search. If you provide the {@link IdentityType}
|
||||||
|
* base interface any of its sub-types will be returned.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
<T extends IdentityType> IdentityQuery<T> createIdentityQuery(Class<T> identityType);
|
||||||
|
}
|
|
@ -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 {
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 <T>
|
||||||
|
*
|
||||||
|
* @author Shane Bryzak
|
||||||
|
*/
|
||||||
|
public class DefaultIdentityQuery<T extends IdentityType> implements IdentityQuery<T> {
|
||||||
|
|
||||||
|
private final Map<QueryParameter, Object[]> parameters = new LinkedHashMap<QueryParameter, Object[]>();
|
||||||
|
private final Class<T> 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<Condition> conditions = new LinkedHashSet<Condition>();
|
||||||
|
private final Set<Sort> ordering = new LinkedHashSet<Sort>();
|
||||||
|
|
||||||
|
public DefaultIdentityQuery(IdentityQueryBuilder queryBuilder, Class<T> identityType, IdentityStore identityStore) {
|
||||||
|
this.queryBuilder = queryBuilder;
|
||||||
|
this.identityStore = identityStore;
|
||||||
|
this.identityType = identityType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IdentityQuery<T> 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<T> where(Condition... condition) {
|
||||||
|
this.conditions.addAll(Arrays.asList(condition));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IdentityQuery<T> sortBy(Sort... sorts) {
|
||||||
|
this.ordering.addAll(Arrays.asList(sorts));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<Sort> getSorting() {
|
||||||
|
return unmodifiableSet(this.ordering);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<T> getIdentityType() {
|
||||||
|
return identityType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<QueryParameter, Object[]> getParameters() {
|
||||||
|
return parameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object[] getParameter(QueryParameter queryParameter) {
|
||||||
|
return this.parameters.get(queryParameter);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<QueryParameter, Object[]> getParameters(Class<?> type) {
|
||||||
|
Map<QueryParameter, Object[]> typedParameters = new HashMap<QueryParameter, Object[]>();
|
||||||
|
|
||||||
|
Set<Map.Entry<QueryParameter, Object[]>> entrySet = this.parameters.entrySet();
|
||||||
|
|
||||||
|
for (Map.Entry<QueryParameter, Object[]> 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<T> 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<T> result = new ArrayList<T>();
|
||||||
|
|
||||||
|
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<T> setOffset(int offset) {
|
||||||
|
this.offset = offset;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IdentityQuery<T> setLimit(int limit) {
|
||||||
|
this.limit = limit;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IdentityQuery<T> setSortParameters(QueryParameter... sortParameters) {
|
||||||
|
this.sortParameters = sortParameters;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IdentityQuery<T> setSortAscending(boolean sortAscending) {
|
||||||
|
this.sortAscending = sortAscending;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IdentityQuery<T> setPaginationContext(Object object) {
|
||||||
|
this.paginationContext = object;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<Condition> getConditions() {
|
||||||
|
return unmodifiableSet(this.conditions);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 <T extends IdentityType> IdentityQuery createIdentityQuery(Class<T> 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 + ".");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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
|
||||||
|
|
||||||
|
<V extends IdentityType> List<V> fetchQueryResults(IdentityQuery<V> identityQuery);
|
||||||
|
|
||||||
|
<V extends IdentityType> int countQueryResults(IdentityQuery<V> identityQuery);
|
||||||
|
|
||||||
|
// // Relationship query
|
||||||
|
//
|
||||||
|
// <V extends Relationship> List<V> fetchQueryResults(RelationshipQuery<V> query);
|
||||||
|
//
|
||||||
|
// <V extends Relationship> int countQueryResults(RelationshipQuery<V> 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);
|
||||||
|
|
||||||
|
}
|
|
@ -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 <a href="mailto:psilva@redhat.com">Pedro Silva</a>
|
||||||
|
*/
|
||||||
|
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<Attribute> 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 <V extends IdentityType> List<V> fetchQueryResults(IdentityQuery<V> identityQuery) {
|
||||||
|
List<V> results = new ArrayList<V>();
|
||||||
|
|
||||||
|
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<SearchResult> 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 <V extends IdentityType> int countQueryResults(IdentityQuery<V> 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<ModificationItem> modItems = new ArrayList<ModificationItem>();
|
||||||
|
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<LDAPUser> 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 <V extends IdentityType> StringBuilder createIdentityTypeSearchFilter(final IdentityQuery<V> 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<? extends Attribute> 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<Object> 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<SearchResult> search = this.operationManager.search(getConfig().getBaseDN(), filter.toString(), entryConfig);
|
||||||
|
|
||||||
|
if (!search.isEmpty()) {
|
||||||
|
SearchResult next = search.get(0);
|
||||||
|
|
||||||
|
Property<AttributedType> parentProperty = PropertyQueries
|
||||||
|
.<AttributedType>createQuery(attributedType.getClass())
|
||||||
|
.addCriteria(new TypedPropertyCriteria(attributedType.getClass())).getFirstResult();
|
||||||
|
|
||||||
|
if (parentProperty != null) {
|
||||||
|
String parentDN = next.getNameInNamespace();
|
||||||
|
String parentBaseDN = parentDN.substring(parentDN.indexOf(",") + 1);
|
||||||
|
Class<? extends AttributedType> 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<String, String> attrMapping, String ldapAttributeName) {
|
||||||
|
for (Map.Entry<String,String> currentAttr : attrMapping.entrySet()) {
|
||||||
|
if (currentAttr.getValue().equalsIgnoreCase(ldapAttributeName)) {
|
||||||
|
return currentAttr.getKey();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> getEntryObjectClasses(final Attributes attributes) throws NamingException {
|
||||||
|
Attribute objectClassesAttribute = attributes.get(LDAPConstants.OBJECT_CLASS);
|
||||||
|
List<String> objectClasses = new ArrayList<String>();
|
||||||
|
|
||||||
|
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<String, String> mappedProperties = mappingConfig.getMappedProperties();
|
||||||
|
|
||||||
|
for (String propertyName : mappedProperties.keySet()) {
|
||||||
|
if (!mappingConfig.getReadOnlyAttributes().contains(propertyName) && (isCreate || !mappingConfig.getBindingProperty().getName().equals(propertyName))) {
|
||||||
|
Property<Object> property = PropertyQueries
|
||||||
|
.<Object>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<? extends AttributedType> 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<String> idProperty = mappingConfig.getIdProperty();
|
||||||
|
|
||||||
|
String baseDN;
|
||||||
|
|
||||||
|
if (mappingConfig.getBaseDN() == null || !appendBaseDN) {
|
||||||
|
baseDN = "";
|
||||||
|
} else {
|
||||||
|
baseDN = LDAPConstants.COMMA + getBaseDN(attributedType);
|
||||||
|
}
|
||||||
|
|
||||||
|
Property<String> 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<AttributedType> parentProperty = PropertyQueries
|
||||||
|
.<AttributedType>createQuery(attributedType.getClass())
|
||||||
|
.addCriteria(new TypedPropertyCriteria(attributedType.getClass())).getFirstResult();
|
||||||
|
|
||||||
|
if (parentProperty != null) {
|
||||||
|
AttributedType parentType = parentProperty.getValue(attributedType);
|
||||||
|
|
||||||
|
if (parentType != null) {
|
||||||
|
Property<String> 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<AttributedType> parentProperty = PropertyQueries
|
||||||
|
.<AttributedType>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<SearchResult> 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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<Class<? extends AttributedType>, LDAPMappingConfiguration> mappingConfig = new HashMap<Class<? extends AttributedType>, 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<? extends AttributedType> clazz) {
|
||||||
|
LDAPMappingConfiguration mappingConfig = new LDAPMappingConfiguration(clazz);
|
||||||
|
this.mappingConfig.put(clazz, mappingConfig);
|
||||||
|
return mappingConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class<? extends AttributedType> getSupportedTypeByBaseDN(String entryDN, List<String> 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<? extends AttributedType> 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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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<? extends AttributedType> mappedClass;
|
||||||
|
private Set<String> objectClasses;
|
||||||
|
private String baseDN;
|
||||||
|
private final Map<String, String> mappedProperties = new HashMap<String, String>();
|
||||||
|
private Property<String> idProperty;
|
||||||
|
private Class<? extends AttributedType> relatedAttributedType;
|
||||||
|
private String parentMembershipAttributeName;
|
||||||
|
private Map<String, String> parentMapping = new HashMap<String, String>();
|
||||||
|
private final Set<String> readOnlyAttributes = new HashSet<String>();
|
||||||
|
private int hierarchySearchDepth;
|
||||||
|
private Property<String> bindingProperty;
|
||||||
|
|
||||||
|
public LDAPMappingConfiguration(Class<? extends AttributedType> mappedClass) {
|
||||||
|
this.mappedClass = mappedClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class<? extends AttributedType> getMappedClass() {
|
||||||
|
return this.mappedClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<String> getObjectClasses() {
|
||||||
|
return this.objectClasses;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBaseDN() {
|
||||||
|
return this.baseDN;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getMappedProperties() {
|
||||||
|
return this.mappedProperties;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Property<String> getIdProperty() {
|
||||||
|
return this.idProperty;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Property<String> getBindingProperty() {
|
||||||
|
return this.bindingProperty;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class<? extends AttributedType> getRelatedAttributedType() {
|
||||||
|
return this.relatedAttributedType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getParentMembershipAttributeName() {
|
||||||
|
return this.parentMembershipAttributeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getParentMapping() {
|
||||||
|
return this.parentMapping;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<String> getReadOnlyAttributes() {
|
||||||
|
return this.readOnlyAttributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHierarchySearchDepth() {
|
||||||
|
return this.hierarchySearchDepth;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Property getBindingProperty(final String bindingPropertyName) {
|
||||||
|
Property bindingProperty = PropertyQueries
|
||||||
|
.<String>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<String>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return bindingPropertyName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type getBaseType() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<String> 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<String> 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<String> 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
|
||||||
|
.<String>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<? extends AttributedType> relatedAttributedType) {
|
||||||
|
this.relatedAttributedType = relatedAttributedType;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LDAPMappingConfiguration setParentMembershipAttributeName(String parentMembershipAttributeName) {
|
||||||
|
this.parentMembershipAttributeName = parentMembershipAttributeName;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LDAPMappingConfiguration setParentMapping(Map<String, String> 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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>This class provides a set of operations to manage LDAP trees.</p>
|
||||||
|
*
|
||||||
|
* @author Anil Saldhana
|
||||||
|
* @author <a href="mailto:psilva@redhat.com">Pedro Silva</a>
|
||||||
|
*/
|
||||||
|
public class LDAPOperationManager {
|
||||||
|
|
||||||
|
private static final Logger logger = Logger.getLogger(LDAPOperationManager.class);
|
||||||
|
|
||||||
|
private final LDAPIdentityStoreConfiguration config;
|
||||||
|
private final Map<String, Object> connectionProperties;
|
||||||
|
|
||||||
|
public LDAPOperationManager(LDAPIdentityStoreConfiguration config) throws NamingException {
|
||||||
|
this.config = config;
|
||||||
|
this.connectionProperties = Collections.unmodifiableMap(createConnectionProperties());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Modifies the given {@link javax.naming.directory.Attribute} instance using the given DN. This method performs a REPLACE_ATTRIBUTE
|
||||||
|
* operation.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param dn
|
||||||
|
* @param attribute
|
||||||
|
*/
|
||||||
|
public void modifyAttribute(String dn, Attribute attribute) {
|
||||||
|
ModificationItem[] mods = new ModificationItem[]{new ModificationItem(DirContext.REPLACE_ATTRIBUTE, attribute)};
|
||||||
|
modifyAttributes(dn, mods);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Modifies the given {@link Attribute} instances using the given DN. This method performs a REPLACE_ATTRIBUTE
|
||||||
|
* operation.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param dn
|
||||||
|
* @param attributes
|
||||||
|
*/
|
||||||
|
public void modifyAttributes(String dn, NamingEnumeration<Attribute> attributes) {
|
||||||
|
try {
|
||||||
|
List<ModificationItem> modItems = new ArrayList<ModificationItem>();
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Removes the given {@link Attribute} instance using the given DN. This method performs a REMOVE_ATTRIBUTE
|
||||||
|
* operation.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param dn
|
||||||
|
* @param attribute
|
||||||
|
*/
|
||||||
|
public void removeAttribute(String dn, Attribute attribute) {
|
||||||
|
ModificationItem[] mods = new ModificationItem[]{new ModificationItem(DirContext.REMOVE_ATTRIBUTE, attribute)};
|
||||||
|
modifyAttributes(dn, mods);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Adds the given {@link Attribute} instance using the given DN. This method performs a ADD_ATTRIBUTE operation.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param dn
|
||||||
|
* @param attribute
|
||||||
|
*/
|
||||||
|
public void addAttribute(String dn, Attribute attribute) {
|
||||||
|
ModificationItem[] mods = new ModificationItem[]{new ModificationItem(DirContext.ADD_ATTRIBUTE, attribute)};
|
||||||
|
modifyAttributes(dn, mods);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Searches the LDAP tree.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @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<SearchResult>() {
|
||||||
|
@Override
|
||||||
|
public SearchResult execute(LdapContext context) throws NamingException {
|
||||||
|
NamingEnumeration<SearchResult> 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<? extends Attribute> 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<SearchResult> search(final String baseDN, final String filter, LDAPMappingConfiguration mappingConfiguration) throws NamingException {
|
||||||
|
final List<SearchResult> result = new ArrayList<SearchResult>();
|
||||||
|
final SearchControls cons = getSearchControls(mappingConfiguration);
|
||||||
|
|
||||||
|
try {
|
||||||
|
return execute(new LdapOperation<List<SearchResult>>() {
|
||||||
|
@Override
|
||||||
|
public List<SearchResult> execute(LdapContext context) throws NamingException {
|
||||||
|
NamingEnumeration<SearchResult> 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 <V extends IdentityType> List<SearchResult> searchPaginated(final String baseDN, final String filter, LDAPMappingConfiguration mappingConfiguration, final IdentityQuery<V> identityQuery) throws NamingException {
|
||||||
|
final List<SearchResult> result = new ArrayList<SearchResult>();
|
||||||
|
final SearchControls cons = getSearchControls(mappingConfiguration);
|
||||||
|
|
||||||
|
try {
|
||||||
|
return execute(new LdapOperation<List<SearchResult>>() {
|
||||||
|
@Override
|
||||||
|
public List<SearchResult> 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<SearchResult> 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<String> 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 = "<GUID=" + id + ">";
|
||||||
|
|
||||||
|
try {
|
||||||
|
Attributes attributes = execute(new LdapOperation<Attributes>() {
|
||||||
|
@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<SearchResult>() {
|
||||||
|
@Override
|
||||||
|
public SearchResult execute(LdapContext context) throws NamingException {
|
||||||
|
NamingEnumeration<SearchResult> 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Destroys a subcontext with the given DN from the LDAP tree.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param dn
|
||||||
|
*/
|
||||||
|
private void destroySubcontext(LdapContext context, final String dn) {
|
||||||
|
try {
|
||||||
|
NamingEnumeration<Binding> 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Performs a simple authentication using the given DN and password to bind to the authentication context.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param dn
|
||||||
|
* @param password
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean authenticate(String dn, String password) {
|
||||||
|
InitialContext authCtx = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
Hashtable<String, Object> env = new Hashtable<String, Object>(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<Void>() {
|
||||||
|
@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<? extends Attribute> all = attributes.getAll();
|
||||||
|
|
||||||
|
while (all.hasMore()) {
|
||||||
|
Attribute attribute = all.next();
|
||||||
|
|
||||||
|
logger.debugf(" %s = %s", attribute.getID(), attribute.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.debugf("]");
|
||||||
|
}
|
||||||
|
|
||||||
|
execute(new LdapOperation<Void>() {
|
||||||
|
@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<SearchResult> createEmptyEnumeration() {
|
||||||
|
return new NamingEnumeration<SearchResult>() {
|
||||||
|
@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<Object, Object>(this.connectionProperties), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, Object> createConnectionProperties() {
|
||||||
|
HashMap<String, Object> env = new HashMap<String, Object>();
|
||||||
|
|
||||||
|
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> R execute(LdapOperation<R> 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> {
|
||||||
|
R execute(LdapContext context) throws NamingException;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> getReturningAttributes(final LDAPMappingConfiguration mappingConfiguration) {
|
||||||
|
List<String> returningAttributes = new ArrayList<String>();
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Utility class for working with LDAP.</p>
|
||||||
|
*
|
||||||
|
* @author Pedro Igor
|
||||||
|
*/
|
||||||
|
public class LDAPUtil {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Formats the given date.</p>
|
||||||
|
*
|
||||||
|
* @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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Parses dates/time stamps stored in LDAP. Some possible values:
|
||||||
|
* </p>
|
||||||
|
* <ul>
|
||||||
|
* <li>20020228150820</li>
|
||||||
|
* <li>20030228150820Z</li>
|
||||||
|
* <li>20050228150820.12</li>
|
||||||
|
* <li>20060711011740.0Z</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Creates a byte-based {@link String} representation of a raw byte array representing the value of the
|
||||||
|
* <code>objectGUID</code> attribute retrieved from Active Directory.</p>
|
||||||
|
*
|
||||||
|
* <p>The returned string is useful to perform queries on AD based on the <code>objectGUID</code> value. Eg.:</p>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* String filter = "(&(objectClass=*)(objectGUID" + EQUAL + convertObjectGUIToByteString(objectGUID) + "))";
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param objectGUID A raw byte array representing the value of the <code>objectGUID</code> 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Decode a raw byte array representing the value of the <code>objectGUID</code> attribute retrieved from Active
|
||||||
|
* Directory.</p>
|
||||||
|
*
|
||||||
|
* <p>The returned string is useful to directly bind an entry. Eg.:</p>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* String bindingString = decodeObjectGUID(objectGUID);
|
||||||
|
* <br/>
|
||||||
|
* Attributes attributes = ctx.getAttributes(bindingString);
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param objectGUID A raw byte array representing the value of the <code>objectGUID</code> 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -1,14 +1,11 @@
|
||||||
package org.keycloak.account.freemarker.model;
|
package org.keycloak.account.freemarker.model;
|
||||||
|
|
||||||
import org.keycloak.models.ApplicationModel;
|
|
||||||
import org.keycloak.models.ClientModel;
|
import org.keycloak.models.ClientModel;
|
||||||
import org.keycloak.models.ClientSessionModel;
|
import org.keycloak.models.ClientSessionModel;
|
||||||
import org.keycloak.models.OAuthClientModel;
|
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.models.UserSessionModel;
|
import org.keycloak.models.UserSessionModel;
|
||||||
import org.keycloak.util.Time;
|
import org.keycloak.util.Time;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
|
@ -63,23 +60,14 @@ public class SessionsBean {
|
||||||
return Time.toDate(max);
|
return Time.toDate(max);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<String> getApplications() {
|
public Set<String> getClients() {
|
||||||
Set<String> apps = new HashSet<String>();
|
Set<String> clients = new HashSet<String>();
|
||||||
for (ClientSessionModel clientSession : session.getClientSessions()) {
|
for (ClientSessionModel clientSession : session.getClientSessions()) {
|
||||||
ClientModel client = clientSession.getClient();
|
ClientModel client = clientSession.getClient();
|
||||||
if (client instanceof ApplicationModel) apps.add(client.getClientId());
|
clients.add(client.getClientId());
|
||||||
}
|
}
|
||||||
return apps;
|
return clients;
|
||||||
}
|
}
|
||||||
public List<String> getClients() {
|
|
||||||
List<String> apps = new ArrayList<String>();
|
|
||||||
for (ClientSessionModel clientSession : session.getClientSessions()) {
|
|
||||||
ClientModel client = clientSession.getClient();
|
|
||||||
if (client instanceof OAuthClientModel) apps.add(client.getClientId());
|
|
||||||
}
|
|
||||||
return apps;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
<td>${msg("started")}</td>
|
<td>${msg("started")}</td>
|
||||||
<td>${msg("lastAccess")}</td>
|
<td>${msg("lastAccess")}</td>
|
||||||
<td>${msg("expires")}</td>
|
<td>${msg("expires")}</td>
|
||||||
<td>${msg("applications")}</td>
|
|
||||||
<td>${msg("clients")}</td>
|
<td>${msg("clients")}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
@ -26,11 +25,6 @@
|
||||||
<td>${session.started?datetime}</td>
|
<td>${session.started?datetime}</td>
|
||||||
<td>${session.lastAccess?datetime}</td>
|
<td>${session.lastAccess?datetime}</td>
|
||||||
<td>${session.expires?datetime}</td>
|
<td>${session.expires?datetime}</td>
|
||||||
<td>
|
|
||||||
<#list session.applications as app>
|
|
||||||
${app}<br/>
|
|
||||||
</#list>
|
|
||||||
</td>
|
|
||||||
<td>
|
<td>
|
||||||
<#list session.clients as client>
|
<#list session.clients as client>
|
||||||
${client}<br/>
|
${client}<br/>
|
||||||
|
|
|
@ -30,8 +30,7 @@
|
||||||
|
|
||||||
<script src="${resourceUrl}/js/app.js" type="text/javascript"></script>
|
<script src="${resourceUrl}/js/app.js" type="text/javascript"></script>
|
||||||
<script src="${resourceUrl}/js/controllers/realm.js" type="text/javascript"></script>
|
<script src="${resourceUrl}/js/controllers/realm.js" type="text/javascript"></script>
|
||||||
<script src="${resourceUrl}/js/controllers/applications.js" type="text/javascript"></script>
|
<script src="${resourceUrl}/js/controllers/clients.js" type="text/javascript"></script>
|
||||||
<script src="${resourceUrl}/js/controllers/oauth-clients.js" type="text/javascript"></script>
|
|
||||||
<script src="${resourceUrl}/js/controllers/users.js" type="text/javascript"></script>
|
<script src="${resourceUrl}/js/controllers/users.js" type="text/javascript"></script>
|
||||||
<script src="${resourceUrl}/js/loaders.js" type="text/javascript"></script>
|
<script src="${resourceUrl}/js/loaders.js" type="text/javascript"></script>
|
||||||
<script src="${resourceUrl}/js/services.js" type="text/javascript"></script>
|
<script src="${resourceUrl}/js/services.js" type="text/javascript"></script>
|
||||||
|
|
|
@ -212,8 +212,8 @@ module.config([ '$routeProvider', function($routeProvider) {
|
||||||
realm : function(RealmLoader) {
|
realm : function(RealmLoader) {
|
||||||
return RealmLoader();
|
return RealmLoader();
|
||||||
},
|
},
|
||||||
applications : function(ApplicationListLoader) {
|
clients : function(ClientListLoader) {
|
||||||
return ApplicationListLoader();
|
return ClientListLoader();
|
||||||
},
|
},
|
||||||
roles : function(RoleListLoader) {
|
roles : function(RoleListLoader) {
|
||||||
return RoleListLoader();
|
return RoleListLoader();
|
||||||
|
@ -311,8 +311,8 @@ module.config([ '$routeProvider', function($routeProvider) {
|
||||||
user : function(UserLoader) {
|
user : function(UserLoader) {
|
||||||
return UserLoader();
|
return UserLoader();
|
||||||
},
|
},
|
||||||
applications : function(ApplicationListLoader) {
|
clients : function(ClientListLoader) {
|
||||||
return ApplicationListLoader();
|
return ClientListLoader();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
controller : 'UserRoleMappingCtrl'
|
controller : 'UserRoleMappingCtrl'
|
||||||
|
@ -369,8 +369,8 @@ module.config([ '$routeProvider', function($routeProvider) {
|
||||||
roles : function(RoleListLoader) {
|
roles : function(RoleListLoader) {
|
||||||
return RoleListLoader();
|
return RoleListLoader();
|
||||||
},
|
},
|
||||||
applications : function(ApplicationListLoader) {
|
clients : function(ClientListLoader) {
|
||||||
return ApplicationListLoader();
|
return ClientListLoader();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
controller : 'RoleDetailCtrl'
|
controller : 'RoleDetailCtrl'
|
||||||
|
@ -387,8 +387,8 @@ module.config([ '$routeProvider', function($routeProvider) {
|
||||||
roles : function(RoleListLoader) {
|
roles : function(RoleListLoader) {
|
||||||
return RoleListLoader();
|
return RoleListLoader();
|
||||||
},
|
},
|
||||||
applications : function(ApplicationListLoader) {
|
clients : function(ClientListLoader) {
|
||||||
return ApplicationListLoader();
|
return ClientListLoader();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
controller : 'RoleDetailCtrl'
|
controller : 'RoleDetailCtrl'
|
||||||
|
@ -406,14 +406,14 @@ module.config([ '$routeProvider', function($routeProvider) {
|
||||||
controller : 'RoleListCtrl'
|
controller : 'RoleListCtrl'
|
||||||
})
|
})
|
||||||
|
|
||||||
.when('/create/role/:realm/applications/:application', {
|
.when('/create/role/:realm/clients/:client', {
|
||||||
templateUrl : resourceUrl + '/partials/application-role-detail.html',
|
templateUrl : resourceUrl + '/partials/client-role-detail.html',
|
||||||
resolve : {
|
resolve : {
|
||||||
realm : function(RealmLoader) {
|
realm : function(RealmLoader) {
|
||||||
return RealmLoader();
|
return RealmLoader();
|
||||||
},
|
},
|
||||||
application : function(ApplicationLoader) {
|
client : function(ClientLoader) {
|
||||||
return ApplicationLoader();
|
return ClientLoader();
|
||||||
},
|
},
|
||||||
role : function() {
|
role : function() {
|
||||||
return {};
|
return {};
|
||||||
|
@ -421,56 +421,56 @@ module.config([ '$routeProvider', function($routeProvider) {
|
||||||
roles : function(RoleListLoader) {
|
roles : function(RoleListLoader) {
|
||||||
return RoleListLoader();
|
return RoleListLoader();
|
||||||
},
|
},
|
||||||
applications : function(ApplicationListLoader) {
|
clients : function(ClientListLoader) {
|
||||||
return ApplicationListLoader();
|
return ClientListLoader();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
controller : 'ApplicationRoleDetailCtrl'
|
controller : 'ClientRoleDetailCtrl'
|
||||||
})
|
})
|
||||||
.when('/realms/:realm/applications/:application/roles/:role', {
|
.when('/realms/:realm/clients/:client/roles/:role', {
|
||||||
templateUrl : resourceUrl + '/partials/application-role-detail.html',
|
templateUrl : resourceUrl + '/partials/client-role-detail.html',
|
||||||
resolve : {
|
resolve : {
|
||||||
realm : function(RealmLoader) {
|
realm : function(RealmLoader) {
|
||||||
return RealmLoader();
|
return RealmLoader();
|
||||||
},
|
},
|
||||||
application : function(ApplicationLoader) {
|
client : function(ClientLoader) {
|
||||||
return ApplicationLoader();
|
return ClientLoader();
|
||||||
},
|
},
|
||||||
role : function(ApplicationRoleLoader) {
|
role : function(ClientRoleLoader) {
|
||||||
return ApplicationRoleLoader();
|
return ClientRoleLoader();
|
||||||
},
|
},
|
||||||
roles : function(RoleListLoader) {
|
roles : function(RoleListLoader) {
|
||||||
return RoleListLoader();
|
return RoleListLoader();
|
||||||
},
|
},
|
||||||
applications : function(ApplicationListLoader) {
|
clients : function(ClientListLoader) {
|
||||||
return ApplicationListLoader();
|
return ClientListLoader();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
controller : 'ApplicationRoleDetailCtrl'
|
controller : 'ClientRoleDetailCtrl'
|
||||||
})
|
})
|
||||||
.when('/realms/:realm/applications/:application/mappers', {
|
.when('/realms/:realm/clients/:client/mappers', {
|
||||||
templateUrl : resourceUrl + '/partials/application-mappers.html',
|
templateUrl : resourceUrl + '/partials/client-mappers.html',
|
||||||
resolve : {
|
resolve : {
|
||||||
realm : function(RealmLoader) {
|
realm : function(RealmLoader) {
|
||||||
return RealmLoader();
|
return RealmLoader();
|
||||||
},
|
},
|
||||||
application : function(ApplicationLoader) {
|
client : function(ClientLoader) {
|
||||||
return ApplicationLoader();
|
return ClientLoader();
|
||||||
},
|
},
|
||||||
serverInfo : function(ServerInfoLoader) {
|
serverInfo : function(ServerInfoLoader) {
|
||||||
return ServerInfoLoader();
|
return ServerInfoLoader();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
controller : 'ApplicationProtocolMapperListCtrl'
|
controller : 'ClientProtocolMapperListCtrl'
|
||||||
})
|
})
|
||||||
.when('/realms/:realm/applications/:application/add-mappers', {
|
.when('/realms/:realm/clients/:client/add-mappers', {
|
||||||
templateUrl : resourceUrl + '/partials/application-mappers-add.html',
|
templateUrl : resourceUrl + '/partials/client-mappers-add.html',
|
||||||
resolve : {
|
resolve : {
|
||||||
realm : function(RealmLoader) {
|
realm : function(RealmLoader) {
|
||||||
return RealmLoader();
|
return RealmLoader();
|
||||||
},
|
},
|
||||||
application : function(ApplicationLoader) {
|
client : function(ClientLoader) {
|
||||||
return ApplicationLoader();
|
return ClientLoader();
|
||||||
},
|
},
|
||||||
serverInfo : function(ServerInfoLoader) {
|
serverInfo : function(ServerInfoLoader) {
|
||||||
return ServerInfoLoader();
|
return ServerInfoLoader();
|
||||||
|
@ -478,26 +478,26 @@ module.config([ '$routeProvider', function($routeProvider) {
|
||||||
},
|
},
|
||||||
controller : 'AddBuiltinProtocolMapperCtrl'
|
controller : 'AddBuiltinProtocolMapperCtrl'
|
||||||
})
|
})
|
||||||
.when('/realms/:realm/applications/:application/mappers/:id', {
|
.when('/realms/:realm/clients/:client/mappers/:id', {
|
||||||
templateUrl : resourceUrl + '/partials/protocol-mapper-detail.html',
|
templateUrl : resourceUrl + '/partials/protocol-mapper-detail.html',
|
||||||
resolve : {
|
resolve : {
|
||||||
realm : function(RealmLoader) {
|
realm : function(RealmLoader) {
|
||||||
return RealmLoader();
|
return RealmLoader();
|
||||||
},
|
},
|
||||||
application : function(ApplicationLoader) {
|
client : function(ClientLoader) {
|
||||||
return ApplicationLoader();
|
return ClientLoader();
|
||||||
},
|
},
|
||||||
serverInfo : function(ServerInfoLoader) {
|
serverInfo : function(ServerInfoLoader) {
|
||||||
return ServerInfoLoader();
|
return ServerInfoLoader();
|
||||||
},
|
},
|
||||||
mapper : function(ApplicationProtocolMapperLoader) {
|
mapper : function(ClientProtocolMapperLoader) {
|
||||||
return ApplicationProtocolMapperLoader();
|
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',
|
templateUrl : resourceUrl + '/partials/protocol-mapper-detail.html',
|
||||||
resolve : {
|
resolve : {
|
||||||
realm : function(RealmLoader) {
|
realm : function(RealmLoader) {
|
||||||
|
@ -506,297 +506,231 @@ module.config([ '$routeProvider', function($routeProvider) {
|
||||||
serverInfo : function(ServerInfoLoader) {
|
serverInfo : function(ServerInfoLoader) {
|
||||||
return ServerInfoLoader();
|
return ServerInfoLoader();
|
||||||
},
|
},
|
||||||
application : function(ApplicationLoader) {
|
client : function(ClientLoader) {
|
||||||
return ApplicationLoader();
|
return ClientLoader();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
controller : 'ApplicationProtocolMapperCreateCtrl'
|
controller : 'ClientProtocolMapperCreateCtrl'
|
||||||
})
|
})
|
||||||
|
.when('/realms/:realm/clients/:client/sessions', {
|
||||||
.when('/realms/:realm/oauth-clients/:oauth/mappers', {
|
templateUrl : resourceUrl + '/partials/client-sessions.html',
|
||||||
templateUrl : resourceUrl + '/partials/oauth-client-mappers.html',
|
|
||||||
resolve : {
|
resolve : {
|
||||||
realm : function(RealmLoader) {
|
realm : function(RealmLoader) {
|
||||||
return RealmLoader();
|
return RealmLoader();
|
||||||
},
|
},
|
||||||
oauth : function(OAuthClientLoader) {
|
client : function(ClientLoader) {
|
||||||
return OAuthClientLoader();
|
return ClientLoader();
|
||||||
},
|
},
|
||||||
serverInfo : function(ServerInfoLoader) {
|
sessionCount : function(ClientSessionCountLoader) {
|
||||||
return ServerInfoLoader();
|
return ClientSessionCountLoader();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
controller : 'OAuthClientProtocolMapperListCtrl'
|
controller : 'ClientSessionsCtrl'
|
||||||
})
|
})
|
||||||
.when('/realms/:realm/oauth-clients/:oauth/add-mappers', {
|
.when('/realms/:realm/clients/:client/credentials', {
|
||||||
templateUrl : resourceUrl + '/partials/oauth-client-mappers-add.html',
|
templateUrl : resourceUrl + '/partials/client-credentials.html',
|
||||||
resolve : {
|
resolve : {
|
||||||
realm : function(RealmLoader) {
|
realm : function(RealmLoader) {
|
||||||
return RealmLoader();
|
return RealmLoader();
|
||||||
},
|
},
|
||||||
oauth : function(OAuthClientLoader) {
|
client : function(ClientLoader) {
|
||||||
return OAuthClientLoader();
|
return ClientLoader();
|
||||||
},
|
|
||||||
serverInfo : function(ServerInfoLoader) {
|
|
||||||
return ServerInfoLoader();
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
controller : 'OAuthClientAddBuiltinProtocolMapperCtrl'
|
controller : 'ClientCredentialsCtrl'
|
||||||
})
|
})
|
||||||
.when('/realms/:realm/oauth-clients/:oauth/mappers/:id', {
|
.when('/realms/:realm/clients/:client/identity-provider', {
|
||||||
templateUrl : resourceUrl + '/partials/oauth-client-protocol-mapper-detail.html',
|
templateUrl : resourceUrl + '/partials/client-identity-provider.html',
|
||||||
resolve : {
|
resolve : {
|
||||||
realm : function(RealmLoader) {
|
realm : function(RealmLoader) {
|
||||||
return RealmLoader();
|
return RealmLoader();
|
||||||
},
|
},
|
||||||
oauth : function(OAuthClientLoader) {
|
client : function(ClientLoader) {
|
||||||
return OAuthClientLoader();
|
return ClientLoader();
|
||||||
},
|
|
||||||
serverInfo : function(ServerInfoLoader) {
|
|
||||||
return ServerInfoLoader();
|
|
||||||
},
|
|
||||||
mapper : function(OAuthClientProtocolMapperLoader) {
|
|
||||||
return OAuthClientProtocolMapperLoader();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
controller : 'OAuthClientProtocolMapperCtrl'
|
controller : 'ClientIdentityProviderCtrl'
|
||||||
})
|
})
|
||||||
.when('/create/oauth-client/:realm/:oauth/mappers', {
|
.when('/realms/:realm/clients/:client/clustering', {
|
||||||
templateUrl : resourceUrl + '/partials/oauth-client-protocol-mapper-detail.html',
|
templateUrl : resourceUrl + '/partials/client-clustering.html',
|
||||||
resolve : {
|
resolve : {
|
||||||
realm : function(RealmLoader) {
|
realm : function(RealmLoader) {
|
||||||
return RealmLoader();
|
return RealmLoader();
|
||||||
},
|
},
|
||||||
serverInfo : function(ServerInfoLoader) {
|
client : function(ClientLoader) {
|
||||||
return ServerInfoLoader();
|
return ClientLoader();
|
||||||
},
|
|
||||||
oauth : function(OAuthClientLoader) {
|
|
||||||
return OAuthClientLoader();
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
controller : 'OAuthClientProtocolMapperCreateCtrl'
|
controller : 'ClientClusteringCtrl'
|
||||||
})
|
})
|
||||||
|
.when('/register-node/realms/:realm/clients/:client/clustering', {
|
||||||
.when('/realms/:realm/applications/:application/sessions', {
|
templateUrl : resourceUrl + '/partials/client-clustering-node.html',
|
||||||
templateUrl : resourceUrl + '/partials/application-sessions.html',
|
|
||||||
resolve : {
|
resolve : {
|
||||||
realm : function(RealmLoader) {
|
realm : function(RealmLoader) {
|
||||||
return RealmLoader();
|
return RealmLoader();
|
||||||
},
|
},
|
||||||
application : function(ApplicationLoader) {
|
client : function(ClientLoader) {
|
||||||
return ApplicationLoader();
|
return ClientLoader();
|
||||||
},
|
|
||||||
sessionCount : function(ApplicationSessionCountLoader) {
|
|
||||||
return ApplicationSessionCountLoader();
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
controller : 'ApplicationSessionsCtrl'
|
controller : 'ClientClusteringNodeCtrl'
|
||||||
})
|
})
|
||||||
.when('/realms/:realm/applications/:application/credentials', {
|
.when('/realms/:realm/clients/:client/clustering/:node', {
|
||||||
templateUrl : resourceUrl + '/partials/application-credentials.html',
|
templateUrl : resourceUrl + '/partials/client-clustering-node.html',
|
||||||
resolve : {
|
resolve : {
|
||||||
realm : function(RealmLoader) {
|
realm : function(RealmLoader) {
|
||||||
return RealmLoader();
|
return RealmLoader();
|
||||||
},
|
},
|
||||||
application : function(ApplicationLoader) {
|
client : function(ClientLoader) {
|
||||||
return ApplicationLoader();
|
return ClientLoader();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
controller : 'ApplicationCredentialsCtrl'
|
controller : 'ClientClusteringNodeCtrl'
|
||||||
})
|
})
|
||||||
.when('/realms/:realm/applications/:application/identity-provider', {
|
.when('/realms/:realm/clients/:client/saml/keys', {
|
||||||
templateUrl : resourceUrl + '/partials/application-identity-provider.html',
|
templateUrl : resourceUrl + '/partials/client-saml-keys.html',
|
||||||
resolve : {
|
resolve : {
|
||||||
realm : function(RealmLoader) {
|
realm : function(RealmLoader) {
|
||||||
return RealmLoader();
|
return RealmLoader();
|
||||||
},
|
},
|
||||||
application : function(ApplicationLoader) {
|
client : function(ClientLoader) {
|
||||||
return ApplicationLoader();
|
return ClientLoader();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
controller : 'ApplicationIdentityProviderCtrl'
|
controller : 'ClientSamlKeyCtrl'
|
||||||
})
|
})
|
||||||
.when('/realms/:realm/applications/:application/clustering', {
|
.when('/realms/:realm/clients/:client/saml/:keyType/import/:attribute', {
|
||||||
templateUrl : resourceUrl + '/partials/application-clustering.html',
|
templateUrl : resourceUrl + '/partials/client-saml-key-import.html',
|
||||||
resolve : {
|
resolve : {
|
||||||
realm : function(RealmLoader) {
|
realm : function(RealmLoader) {
|
||||||
return RealmLoader();
|
return RealmLoader();
|
||||||
},
|
},
|
||||||
application : function(ApplicationLoader) {
|
client : function(ClientLoader) {
|
||||||
return ApplicationLoader();
|
return ClientLoader();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
controller : 'ApplicationClusteringCtrl'
|
controller : 'ClientCertificateImportCtrl'
|
||||||
})
|
})
|
||||||
.when('/register-node/realms/:realm/applications/:application/clustering', {
|
.when('/realms/:realm/clients/:client/saml/:keyType/export/:attribute', {
|
||||||
templateUrl : resourceUrl + '/partials/application-clustering-node.html',
|
templateUrl : resourceUrl + '/partials/client-saml-key-export.html',
|
||||||
resolve : {
|
resolve : {
|
||||||
realm : function(RealmLoader) {
|
realm : function(RealmLoader) {
|
||||||
return RealmLoader();
|
return RealmLoader();
|
||||||
},
|
},
|
||||||
application : function(ApplicationLoader) {
|
client : function(ClientLoader) {
|
||||||
return ApplicationLoader();
|
return ClientLoader();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
controller : 'ApplicationClusteringNodeCtrl'
|
controller : 'ClientCertificateExportCtrl'
|
||||||
})
|
})
|
||||||
.when('/realms/:realm/applications/:application/clustering/:node', {
|
.when('/realms/:realm/clients/:client/roles', {
|
||||||
templateUrl : resourceUrl + '/partials/application-clustering-node.html',
|
templateUrl : resourceUrl + '/partials/client-role-list.html',
|
||||||
resolve : {
|
resolve : {
|
||||||
realm : function(RealmLoader) {
|
realm : function(RealmLoader) {
|
||||||
return RealmLoader();
|
return RealmLoader();
|
||||||
},
|
},
|
||||||
application : function(ApplicationLoader) {
|
client : function(ClientLoader) {
|
||||||
return ApplicationLoader();
|
return ClientLoader();
|
||||||
|
},
|
||||||
|
roles : function(ClientRoleListLoader) {
|
||||||
|
return ClientRoleListLoader();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
controller : 'ApplicationClusteringNodeCtrl'
|
controller : 'ClientRoleListCtrl'
|
||||||
})
|
})
|
||||||
.when('/realms/:realm/applications/:application/saml/keys', {
|
.when('/realms/:realm/clients/:client/revocation', {
|
||||||
templateUrl : resourceUrl + '/partials/application-saml-keys.html',
|
templateUrl : resourceUrl + '/partials/client-revocation.html',
|
||||||
resolve : {
|
resolve : {
|
||||||
realm : function(RealmLoader) {
|
realm : function(RealmLoader) {
|
||||||
return RealmLoader();
|
return RealmLoader();
|
||||||
},
|
},
|
||||||
application : function(ApplicationLoader) {
|
client : function(ClientLoader) {
|
||||||
return ApplicationLoader();
|
return ClientLoader();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
controller : 'ApplicationSamlKeyCtrl'
|
controller : 'ClientRevocationCtrl'
|
||||||
})
|
})
|
||||||
.when('/realms/:realm/applications/:application/saml/:keyType/import/:attribute', {
|
.when('/realms/:realm/clients/:client/scope-mappings', {
|
||||||
templateUrl : resourceUrl + '/partials/application-saml-key-import.html',
|
templateUrl : resourceUrl + '/partials/client-scope-mappings.html',
|
||||||
resolve : {
|
resolve : {
|
||||||
realm : function(RealmLoader) {
|
realm : function(RealmLoader) {
|
||||||
return RealmLoader();
|
return RealmLoader();
|
||||||
},
|
},
|
||||||
application : function(ApplicationLoader) {
|
client : function(ClientLoader) {
|
||||||
return ApplicationLoader();
|
return ClientLoader();
|
||||||
|
},
|
||||||
|
clients : function(ClientListLoader) {
|
||||||
|
return ClientListLoader();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
controller : 'ApplicationCertificateImportCtrl'
|
controller : 'ClientScopeMappingCtrl'
|
||||||
})
|
})
|
||||||
.when('/realms/:realm/applications/:application/saml/:keyType/export/:attribute', {
|
.when('/realms/:realm/clients/:client/installation', {
|
||||||
templateUrl : resourceUrl + '/partials/application-saml-key-export.html',
|
templateUrl : resourceUrl + '/partials/client-installation.html',
|
||||||
resolve : {
|
resolve : {
|
||||||
realm : function(RealmLoader) {
|
realm : function(RealmLoader) {
|
||||||
return RealmLoader();
|
return RealmLoader();
|
||||||
},
|
},
|
||||||
application : function(ApplicationLoader) {
|
client : function(ClientLoader) {
|
||||||
return ApplicationLoader();
|
return ClientLoader();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
controller : 'ApplicationCertificateExportCtrl'
|
controller : 'ClientInstallationCtrl'
|
||||||
})
|
})
|
||||||
.when('/realms/:realm/applications/:application/roles', {
|
.when('/create/client/:realm', {
|
||||||
templateUrl : resourceUrl + '/partials/application-role-list.html',
|
templateUrl : resourceUrl + '/partials/client-detail.html',
|
||||||
resolve : {
|
resolve : {
|
||||||
realm : function(RealmLoader) {
|
realm : function(RealmLoader) {
|
||||||
return RealmLoader();
|
return RealmLoader();
|
||||||
},
|
},
|
||||||
application : function(ApplicationLoader) {
|
clients : function(ClientListLoader) {
|
||||||
return ApplicationLoader();
|
return ClientListLoader();
|
||||||
},
|
},
|
||||||
roles : function(ApplicationRoleListLoader) {
|
client : function() {
|
||||||
return ApplicationRoleListLoader();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
controller : 'ApplicationRoleListCtrl'
|
|
||||||
})
|
|
||||||
.when('/realms/:realm/applications/:application/revocation', {
|
|
||||||
templateUrl : resourceUrl + '/partials/application-revocation.html',
|
|
||||||
resolve : {
|
|
||||||
realm : function(RealmLoader) {
|
|
||||||
return RealmLoader();
|
|
||||||
},
|
|
||||||
application : function(ApplicationLoader) {
|
|
||||||
return ApplicationLoader();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
controller : 'ApplicationRevocationCtrl'
|
|
||||||
})
|
|
||||||
.when('/realms/:realm/applications/:application/scope-mappings', {
|
|
||||||
templateUrl : resourceUrl + '/partials/application-scope-mappings.html',
|
|
||||||
resolve : {
|
|
||||||
realm : function(RealmLoader) {
|
|
||||||
return RealmLoader();
|
|
||||||
},
|
|
||||||
application : function(ApplicationLoader) {
|
|
||||||
return ApplicationLoader();
|
|
||||||
},
|
|
||||||
applications : function(ApplicationListLoader) {
|
|
||||||
return ApplicationListLoader();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
controller : 'ApplicationScopeMappingCtrl'
|
|
||||||
})
|
|
||||||
.when('/realms/:realm/applications/:application/installation', {
|
|
||||||
templateUrl : resourceUrl + '/partials/application-installation.html',
|
|
||||||
resolve : {
|
|
||||||
realm : function(RealmLoader) {
|
|
||||||
return RealmLoader();
|
|
||||||
},
|
|
||||||
application : function(ApplicationLoader) {
|
|
||||||
return ApplicationLoader();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
controller : 'ApplicationInstallationCtrl'
|
|
||||||
})
|
|
||||||
.when('/create/application/:realm', {
|
|
||||||
templateUrl : resourceUrl + '/partials/application-detail.html',
|
|
||||||
resolve : {
|
|
||||||
realm : function(RealmLoader) {
|
|
||||||
return RealmLoader();
|
|
||||||
},
|
|
||||||
applications : function(ApplicationListLoader) {
|
|
||||||
return ApplicationListLoader();
|
|
||||||
},
|
|
||||||
application : function() {
|
|
||||||
return {};
|
return {};
|
||||||
},
|
},
|
||||||
serverInfo : function(ServerInfoLoader) {
|
serverInfo : function(ServerInfoLoader) {
|
||||||
return ServerInfoLoader();
|
return ServerInfoLoader();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
controller : 'ApplicationDetailCtrl'
|
controller : 'ClientDetailCtrl'
|
||||||
})
|
})
|
||||||
.when('/realms/:realm/applications/:application', {
|
.when('/realms/:realm/clients/:client', {
|
||||||
templateUrl : resourceUrl + '/partials/application-detail.html',
|
templateUrl : resourceUrl + '/partials/client-detail.html',
|
||||||
resolve : {
|
resolve : {
|
||||||
realm : function(RealmLoader) {
|
realm : function(RealmLoader) {
|
||||||
return RealmLoader();
|
return RealmLoader();
|
||||||
},
|
},
|
||||||
applications : function(ApplicationListLoader) {
|
clients : function(ClientListLoader) {
|
||||||
return ApplicationListLoader();
|
return ClientListLoader();
|
||||||
},
|
},
|
||||||
application : function(ApplicationLoader) {
|
client : function(ClientLoader) {
|
||||||
return ApplicationLoader();
|
return ClientLoader();
|
||||||
},
|
},
|
||||||
serverInfo : function(ServerInfoLoader) {
|
serverInfo : function(ServerInfoLoader) {
|
||||||
return ServerInfoLoader();
|
return ServerInfoLoader();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
controller : 'ApplicationDetailCtrl'
|
controller : 'ClientDetailCtrl'
|
||||||
})
|
})
|
||||||
.when('/realms/:realm/applications', {
|
.when('/realms/:realm/clients', {
|
||||||
templateUrl : resourceUrl + '/partials/application-list.html',
|
templateUrl : resourceUrl + '/partials/client-list.html',
|
||||||
resolve : {
|
resolve : {
|
||||||
realm : function(RealmLoader) {
|
realm : function(RealmLoader) {
|
||||||
return RealmLoader();
|
return RealmLoader();
|
||||||
},
|
},
|
||||||
applications : function(ApplicationListLoader) {
|
clients : function(ClientListLoader) {
|
||||||
return ApplicationListLoader();
|
return ClientListLoader();
|
||||||
},
|
},
|
||||||
serverInfo : function(ServerInfoLoader) {
|
serverInfo : function(ServerInfoLoader) {
|
||||||
return ServerInfoLoader();
|
return ServerInfoLoader();
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
controller : 'ApplicationListCtrl'
|
controller : 'ClientListCtrl'
|
||||||
})
|
})
|
||||||
.when('/import/application/:realm', {
|
.when('/import/client/:realm', {
|
||||||
templateUrl : resourceUrl + '/partials/application-import.html',
|
templateUrl : resourceUrl + '/partials/client-import.html',
|
||||||
resolve : {
|
resolve : {
|
||||||
realm : function(RealmLoader) {
|
realm : function(RealmLoader) {
|
||||||
return RealmLoader();
|
return RealmLoader();
|
||||||
|
@ -805,129 +739,8 @@ module.config([ '$routeProvider', function($routeProvider) {
|
||||||
return ServerInfoLoader();
|
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('/', {
|
.when('/', {
|
||||||
templateUrl : resourceUrl + '/partials/home.html',
|
templateUrl : resourceUrl + '/partials/home.html',
|
||||||
controller : 'HomeCtrl'
|
controller : 'HomeCtrl'
|
||||||
|
@ -959,8 +772,8 @@ module.config([ '$routeProvider', function($routeProvider) {
|
||||||
realm : function(RealmLoader) {
|
realm : function(RealmLoader) {
|
||||||
return RealmLoader();
|
return RealmLoader();
|
||||||
},
|
},
|
||||||
stats : function(RealmApplicationSessionStatsLoader) {
|
stats : function(RealmClientSessionStatsLoader) {
|
||||||
return RealmApplicationSessionStatsLoader();
|
return RealmClientSessionStatsLoader();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
controller : 'RealmSessionStatsCtrl'
|
controller : 'RealmSessionStatsCtrl'
|
||||||
|
@ -1540,21 +1353,12 @@ module.directive('kcNavigation', function ($compile, Notifications) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
module.directive('kcNavigationApplication', function () {
|
module.directive('kcNavigationClient', function () {
|
||||||
return {
|
return {
|
||||||
scope: true,
|
scope: true,
|
||||||
restrict: 'E',
|
restrict: 'E',
|
||||||
replace: true,
|
replace: true,
|
||||||
templateUrl: resourceUrl + '/templates/kc-navigation-application.html'
|
templateUrl: resourceUrl + '/templates/kc-navigation-client.html'
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
module.directive('kcNavigationOauthClient', function () {
|
|
||||||
return {
|
|
||||||
scope: true,
|
|
||||||
restrict: 'E',
|
|
||||||
replace: true,
|
|
||||||
templateUrl: resourceUrl + '/templates/kc-navigation-oauth-client.html'
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -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();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
|
@ -53,10 +53,6 @@ module.controller('GlobalCtrl', function($scope, $http, Auth, WhoAmI, Current, $
|
||||||
return getAccess('view-realm') || this.manageRealm;
|
return getAccess('view-realm') || this.manageRealm;
|
||||||
},
|
},
|
||||||
|
|
||||||
get viewApplications() {
|
|
||||||
return getAccess('view-applications') || this.manageApplications;
|
|
||||||
},
|
|
||||||
|
|
||||||
get viewClients() {
|
get viewClients() {
|
||||||
return getAccess('view-clients') || this.manageClients;
|
return getAccess('view-clients') || this.manageClients;
|
||||||
},
|
},
|
||||||
|
@ -73,10 +69,6 @@ module.controller('GlobalCtrl', function($scope, $http, Auth, WhoAmI, Current, $
|
||||||
return getAccess('manage-realm');
|
return getAccess('manage-realm');
|
||||||
},
|
},
|
||||||
|
|
||||||
get manageApplications() {
|
|
||||||
return getAccess('manage-applications');
|
|
||||||
},
|
|
||||||
|
|
||||||
get manageClients() {
|
get manageClients() {
|
||||||
return getAccess('manage-clients');
|
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');
|
console.log('RealmDefaultRolesCtrl');
|
||||||
|
|
||||||
|
@ -494,17 +486,17 @@ module.controller('RealmDefaultRolesCtrl', function ($scope, Realm, realm, appli
|
||||||
$scope.selectedRealmRoles = [];
|
$scope.selectedRealmRoles = [];
|
||||||
$scope.selectedRealmDefRoles = [];
|
$scope.selectedRealmDefRoles = [];
|
||||||
|
|
||||||
$scope.applications = angular.copy(applications);
|
$scope.clients = angular.copy(clients);
|
||||||
for (var i = 0; i < applications.length; i++) {
|
for (var i = 0; i < clients.length; i++) {
|
||||||
if (applications[i].name == 'account') {
|
if (clients[i].name == 'account') {
|
||||||
$scope.application = $scope.applications[i];
|
$scope.client = $scope.clients[i];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.availableAppRoles = [];
|
$scope.availableClientRoles = [];
|
||||||
$scope.selectedAppRoles = [];
|
$scope.selectedClientRoles = [];
|
||||||
$scope.selectedAppDefRoles = [];
|
$scope.selectedClientDefRoles = [];
|
||||||
|
|
||||||
if (!$scope.realm.hasOwnProperty('defaultRoles') || $scope.realm.defaultRoles === null) {
|
if (!$scope.realm.hasOwnProperty('defaultRoles') || $scope.realm.defaultRoles === null) {
|
||||||
$scope.realm.defaultRoles = [];
|
$scope.realm.defaultRoles = [];
|
||||||
|
@ -558,81 +550,81 @@ module.controller('RealmDefaultRolesCtrl', function ($scope, Realm, realm, appli
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.changeApplication = function () {
|
$scope.changeClient = function () {
|
||||||
|
|
||||||
$scope.selectedAppRoles = [];
|
$scope.selectedClientRoles = [];
|
||||||
$scope.selectedAppDefRoles = [];
|
$scope.selectedClientDefRoles = [];
|
||||||
|
|
||||||
// Populate available roles for selected application
|
// Populate available roles for selected client
|
||||||
if ($scope.application) {
|
if ($scope.client) {
|
||||||
var appDefaultRoles = ApplicationRole.query({realm: $scope.realm.realm, application: $scope.application.id}, function () {
|
var appDefaultRoles = ClientRole.query({realm: $scope.realm.realm, client: $scope.client.id}, function () {
|
||||||
|
|
||||||
if (!$scope.application.hasOwnProperty('defaultRoles') || $scope.application.defaultRoles === null) {
|
if (!$scope.client.hasOwnProperty('defaultRoles') || $scope.client.defaultRoles === null) {
|
||||||
$scope.application.defaultRoles = [];
|
$scope.client.defaultRoles = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.availableAppRoles = [];
|
$scope.availableClientRoles = [];
|
||||||
|
|
||||||
for (var i = 0; i < appDefaultRoles.length; i++) {
|
for (var i = 0; i < appDefaultRoles.length; i++) {
|
||||||
var roleName = appDefaultRoles[i].name;
|
var roleName = appDefaultRoles[i].name;
|
||||||
if ($scope.application.defaultRoles.indexOf(roleName) < 0) {
|
if ($scope.client.defaultRoles.indexOf(roleName) < 0) {
|
||||||
$scope.availableAppRoles.push(roleName);
|
$scope.availableClientRoles.push(roleName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} 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).
|
// 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++) {
|
for (var i = 0; i < $scope.selectedClientRoles.length; i++) {
|
||||||
var role = $scope.selectedAppRoles[i];
|
var role = $scope.selectedClientRoles[i];
|
||||||
|
|
||||||
var idx = $scope.application.defaultRoles.indexOf(role);
|
var idx = $scope.client.defaultRoles.indexOf(role);
|
||||||
if (idx < 0) {
|
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) {
|
if (idx != -1) {
|
||||||
$scope.availableAppRoles.splice(idx, 1);
|
$scope.availableClientRoles.splice(idx, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update/save the selected application with new default roles.
|
// Update/save the selected client with new default roles.
|
||||||
Application.update({
|
Client.update({
|
||||||
realm: $scope.realm.realm,
|
realm: $scope.realm.realm,
|
||||||
application: $scope.application.id
|
client: $scope.client.id
|
||||||
}, $scope.application, function () {
|
}, $scope.client, function () {
|
||||||
Notifications.success("Your changes have been saved to the application.");
|
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).
|
// 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++) {
|
for (var i = 0; i < $scope.selectedClientDefRoles.length; i++) {
|
||||||
var role = $scope.selectedAppDefRoles[i];
|
var role = $scope.selectedClientDefRoles[i];
|
||||||
var idx = $scope.application.defaultRoles.indexOf(role);
|
var idx = $scope.client.defaultRoles.indexOf(role);
|
||||||
if (idx != -1) {
|
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) {
|
if (idx < 0) {
|
||||||
$scope.availableAppRoles.push(role);
|
$scope.availableClientRoles.push(role);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update/save the selected application with new default roles.
|
// Update/save the selected client with new default roles.
|
||||||
Application.update({
|
Client.update({
|
||||||
realm: $scope.realm.realm,
|
realm: $scope.realm.realm,
|
||||||
application: $scope.application.id
|
client: $scope.client.id
|
||||||
}, $scope.application, function () {
|
}, $scope.client, function () {
|
||||||
Notifications.success("Your changes have been saved to the application.");
|
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
|
alias : $scope.identityProvider.alias
|
||||||
}, function() {
|
}, function() {
|
||||||
$location.url("/realms/" + realm.realm + "/identity-provider-settings");
|
$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.realm = realm;
|
||||||
$scope.stats = stats;
|
$scope.stats = stats;
|
||||||
|
|
||||||
|
@ -1081,7 +1073,7 @@ module.controller('RealmRevocationCtrl', function($scope, Realm, RealmPushRevoca
|
||||||
var msgStart = successCount>0 ? 'Successfully push notBefore to: ' + globalReqResult.successRequests + ' . ' : '';
|
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');
|
Notifications.error(msgStart + 'Failed to push notBefore to: ' + globalReqResult.failedRequests + '. Verify availability of failed hosts and try again');
|
||||||
} else {
|
} 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,
|
module.controller('RoleDetailCtrl', function($scope, realm, role, roles, clients,
|
||||||
Role, ApplicationRole, RoleById, RoleRealmComposites, RoleApplicationComposites,
|
Role, ClientRole, RoleById, RoleRealmComposites, RoleClientComposites,
|
||||||
$http, $location, Dialog, Notifications) {
|
$http, $location, Dialog, Notifications) {
|
||||||
$scope.realm = realm;
|
$scope.realm = realm;
|
||||||
$scope.role = angular.copy(role);
|
$scope.role = angular.copy(role);
|
||||||
|
@ -1149,8 +1141,8 @@ module.controller('RoleDetailCtrl', function($scope, realm, role, roles, applica
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
roleControl($scope, realm, role, roles, applications,
|
roleControl($scope, realm, role, roles, clients,
|
||||||
ApplicationRole, RoleById, RoleRealmComposites, RoleApplicationComposites,
|
ClientRole, RoleById, RoleRealmComposites, RoleClientComposites,
|
||||||
$http, $location, Notifications, Dialog);
|
$http, $location, Notifications, Dialog);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
module.controller('UserRoleMappingCtrl', function($scope, $http, realm, user, applications, Notifications, RealmRoleMapping,
|
module.controller('UserRoleMappingCtrl', function($scope, $http, realm, user, clients, Notifications, RealmRoleMapping,
|
||||||
ApplicationRoleMapping, AvailableRealmRoleMapping, AvailableApplicationRoleMapping,
|
ClientRoleMapping, AvailableRealmRoleMapping, AvailableClientRoleMapping,
|
||||||
CompositeRealmRoleMapping, CompositeApplicationRoleMapping) {
|
CompositeRealmRoleMapping, CompositeClientRoleMapping) {
|
||||||
$scope.realm = realm;
|
$scope.realm = realm;
|
||||||
$scope.user = user;
|
$scope.user = user;
|
||||||
$scope.selectedRealmRoles = [];
|
$scope.selectedRealmRoles = [];
|
||||||
$scope.selectedRealmMappings = [];
|
$scope.selectedRealmMappings = [];
|
||||||
$scope.realmMappings = [];
|
$scope.realmMappings = [];
|
||||||
$scope.applications = applications;
|
$scope.clients = clients;
|
||||||
$scope.applicationRoles = [];
|
$scope.clientRoles = [];
|
||||||
$scope.applicationComposite = [];
|
$scope.clientComposite = [];
|
||||||
$scope.selectedApplicationRoles = [];
|
$scope.selectedClientRoles = [];
|
||||||
$scope.selectedApplicationMappings = [];
|
$scope.selectedClientMappings = [];
|
||||||
$scope.applicationMappings = [];
|
$scope.clientMappings = [];
|
||||||
$scope.dummymodel = [];
|
$scope.dummymodel = [];
|
||||||
|
|
||||||
$scope.realmMappings = RealmRoleMapping.query({realm : realm.realm, userId : user.username});
|
$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.realmComposite = CompositeRealmRoleMapping.query({realm : realm.realm, userId : user.username});
|
||||||
$scope.selectedRealmMappings = [];
|
$scope.selectedRealmMappings = [];
|
||||||
$scope.selectRealmRoles = [];
|
$scope.selectRealmRoles = [];
|
||||||
if ($scope.application) {
|
if ($scope.client) {
|
||||||
console.log('load available');
|
console.log('load available');
|
||||||
$scope.applicationComposite = CompositeApplicationRoleMapping.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.applicationRoles = AvailableApplicationRoleMapping.query({realm : realm.realm, userId : user.username, application : $scope.application.id});
|
$scope.clientRoles = AvailableClientRoleMapping.query({realm : realm.realm, userId : user.username, client : $scope.client.id});
|
||||||
$scope.applicationMappings = ApplicationRoleMapping.query({realm : realm.realm, userId : user.username, application : $scope.application.id});
|
$scope.clientMappings = ClientRoleMapping.query({realm : realm.realm, userId : user.username, client : $scope.client.id});
|
||||||
$scope.selectedApplicationRoles = [];
|
$scope.selectedClientRoles = [];
|
||||||
$scope.selectedApplicationMappings = [];
|
$scope.selectedClientMappings = [];
|
||||||
}
|
}
|
||||||
Notifications.success("Role mappings updated.");
|
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.realmComposite = CompositeRealmRoleMapping.query({realm : realm.realm, userId : user.username});
|
||||||
$scope.selectedRealmMappings = [];
|
$scope.selectedRealmMappings = [];
|
||||||
$scope.selectRealmRoles = [];
|
$scope.selectRealmRoles = [];
|
||||||
if ($scope.application) {
|
if ($scope.client) {
|
||||||
console.log('load available');
|
console.log('load available');
|
||||||
$scope.applicationComposite = CompositeApplicationRoleMapping.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.applicationRoles = AvailableApplicationRoleMapping.query({realm : realm.realm, userId : user.username, application : $scope.application.id});
|
$scope.clientRoles = AvailableClientRoleMapping.query({realm : realm.realm, userId : user.username, client : $scope.client.id});
|
||||||
$scope.applicationMappings = ApplicationRoleMapping.query({realm : realm.realm, userId : user.username, application : $scope.application.id});
|
$scope.clientMappings = ClientRoleMapping.query({realm : realm.realm, userId : user.username, client : $scope.client.id});
|
||||||
$scope.selectedApplicationRoles = [];
|
$scope.selectedClientRoles = [];
|
||||||
$scope.selectedApplicationMappings = [];
|
$scope.selectedClientMappings = [];
|
||||||
}
|
}
|
||||||
Notifications.success("Role mappings updated.");
|
Notifications.success("Role mappings updated.");
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.addApplicationRole = function() {
|
$scope.addClientRole = function() {
|
||||||
$http.post(authUrl + '/admin/realms/' + realm.realm + '/users/' + user.username + '/role-mappings/applications-by-id/' + $scope.application.id,
|
$http.post(authUrl + '/admin/realms/' + realm.realm + '/users/' + user.username + '/role-mappings/clients-by-id/' + $scope.client.id,
|
||||||
$scope.selectedApplicationRoles).success(function() {
|
$scope.selectedClientRoles).success(function() {
|
||||||
$scope.applicationMappings = ApplicationRoleMapping.query({realm : realm.realm, userId : user.username, application : $scope.application.id});
|
$scope.clientMappings = ClientRoleMapping.query({realm : realm.realm, userId : user.username, client : $scope.client.id});
|
||||||
$scope.applicationRoles = AvailableApplicationRoleMapping.query({realm : realm.realm, userId : user.username, application : $scope.application.id});
|
$scope.clientRoles = AvailableClientRoleMapping.query({realm : realm.realm, userId : user.username, client : $scope.client.id});
|
||||||
$scope.applicationComposite = CompositeApplicationRoleMapping.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.selectedApplicationRoles = [];
|
$scope.selectedClientRoles = [];
|
||||||
$scope.selectedApplicationMappings = [];
|
$scope.selectedClientMappings = [];
|
||||||
Notifications.success("Role mappings updated.");
|
Notifications.success("Role mappings updated.");
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.deleteApplicationRole = function() {
|
$scope.deleteClientRole = function() {
|
||||||
$http.delete(authUrl + '/admin/realms/' + realm.realm + '/users/' + user.username + '/role-mappings/applications-by-id/' + $scope.application.id,
|
$http.delete(authUrl + '/admin/realms/' + realm.realm + '/users/' + user.username + '/role-mappings/clients-by-id/' + $scope.client.id,
|
||||||
{data : $scope.selectedApplicationMappings, headers : {"content-type" : "application/json"}}).success(function() {
|
{data : $scope.selectedClientMappings, headers : {"content-type" : "application/json"}}).success(function() {
|
||||||
$scope.applicationMappings = ApplicationRoleMapping.query({realm : realm.realm, userId : user.username, application : $scope.application.id});
|
$scope.clientMappings = ClientRoleMapping.query({realm : realm.realm, userId : user.username, client : $scope.client.id});
|
||||||
$scope.applicationRoles = AvailableApplicationRoleMapping.query({realm : realm.realm, userId : user.username, application : $scope.application.id});
|
$scope.clientRoles = AvailableClientRoleMapping.query({realm : realm.realm, userId : user.username, client : $scope.client.id});
|
||||||
$scope.applicationComposite = CompositeApplicationRoleMapping.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.selectedApplicationRoles = [];
|
$scope.selectedClientRoles = [];
|
||||||
$scope.selectedApplicationMappings = [];
|
$scope.selectedClientMappings = [];
|
||||||
Notifications.success("Role mappings updated.");
|
Notifications.success("Role mappings updated.");
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
$scope.changeApplication = function() {
|
$scope.changeClient = function() {
|
||||||
console.log('changeApplication');
|
console.log('changeClient');
|
||||||
if ($scope.application) {
|
if ($scope.client) {
|
||||||
console.log('load available');
|
console.log('load available');
|
||||||
$scope.applicationComposite = CompositeApplicationRoleMapping.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.applicationRoles = AvailableApplicationRoleMapping.query({realm : realm.realm, userId : user.username, application : $scope.application.id});
|
$scope.clientRoles = AvailableClientRoleMapping.query({realm : realm.realm, userId : user.username, client : $scope.client.id});
|
||||||
$scope.applicationMappings = ApplicationRoleMapping.query({realm : realm.realm, userId : user.username, application : $scope.application.id});
|
$scope.clientMappings = ClientRoleMapping.query({realm : realm.realm, userId : user.username, client : $scope.client.id});
|
||||||
} else {
|
} else {
|
||||||
$scope.applicationRoles = null;
|
$scope.clientRoles = null;
|
||||||
$scope.applicationMappings = null;
|
$scope.clientMappings = null;
|
||||||
$scope.applicationComposite = null;
|
$scope.clientComposite = null;
|
||||||
}
|
}
|
||||||
$scope.selectedApplicationRoles = [];
|
$scope.selectedClientRoles = [];
|
||||||
$scope.selectedApplicationMappings = [];
|
$scope.selectedClientMappings = [];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -111,7 +111,7 @@ module.controller('UserSessionsCtrl', function($scope, realm, user, sessions, Us
|
||||||
|
|
||||||
$scope.logoutAll = function() {
|
$scope.logoutAll = function() {
|
||||||
UserLogout.save({realm : realm.realm, user: user.username}, 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) {
|
UserSessions.query({realm: realm.realm, user: user.username}, function(updated) {
|
||||||
$scope.sessions = updated;
|
$scope.sessions = updated;
|
||||||
})
|
})
|
||||||
|
|
|
@ -71,35 +71,24 @@ module.factory('RealmSessionStatsLoader', function(Loader, RealmSessionStats, $r
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
module.factory('RealmApplicationSessionStatsLoader', function(Loader, RealmApplicationSessionStats, $route, $q) {
|
module.factory('RealmClientSessionStatsLoader', function(Loader, RealmClientSessionStats, $route, $q) {
|
||||||
return Loader.query(RealmApplicationSessionStats, function() {
|
return Loader.query(RealmClientSessionStats, function() {
|
||||||
return {
|
return {
|
||||||
realm : $route.current.params.realm
|
realm : $route.current.params.realm
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
module.factory('ApplicationProtocolMapperLoader', function(Loader, ApplicationProtocolMapper, $route, $q) {
|
module.factory('ClientProtocolMapperLoader', function(Loader, ClientProtocolMapper, $route, $q) {
|
||||||
return Loader.get(ApplicationProtocolMapper, function() {
|
return Loader.get(ClientProtocolMapper, function() {
|
||||||
return {
|
return {
|
||||||
realm : $route.current.params.realm,
|
realm : $route.current.params.realm,
|
||||||
application : $route.current.params.application,
|
client : $route.current.params.client,
|
||||||
id: $route.current.params.id
|
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) {
|
module.factory('UserLoader', function(Loader, User, $route, $q) {
|
||||||
return Loader.get(User, function() {
|
return Loader.get(User, function() {
|
||||||
return {
|
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 Loader.get(RoleById, function() {
|
||||||
return {
|
return {
|
||||||
realm : $route.current.params.realm,
|
realm : $route.current.params.realm,
|
||||||
application : $route.current.params.application,
|
client : $route.current.params.client,
|
||||||
role : $route.current.params.role
|
role : $route.current.params.role
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
module.factory('ApplicationSessionStatsLoader', function(Loader, ApplicationSessionStats, $route, $q) {
|
module.factory('ClientSessionStatsLoader', function(Loader, ClientSessionStats, $route, $q) {
|
||||||
return Loader.get(ApplicationSessionStats, function() {
|
return Loader.get(ClientSessionStats, function() {
|
||||||
return {
|
return {
|
||||||
realm : $route.current.params.realm,
|
realm : $route.current.params.realm,
|
||||||
application : $route.current.params.application
|
client : $route.current.params.client
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
module.factory('ApplicationSessionCountLoader', function(Loader, ApplicationSessionCount, $route, $q) {
|
module.factory('ClientSessionCountLoader', function(Loader, ClientSessionCount, $route, $q) {
|
||||||
return Loader.get(ApplicationSessionCount, function() {
|
return Loader.get(ClientSessionCount, function() {
|
||||||
return {
|
return {
|
||||||
realm : $route.current.params.realm,
|
realm : $route.current.params.realm,
|
||||||
application : $route.current.params.application
|
client : $route.current.params.client
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
module.factory('ApplicationClaimsLoader', function(Loader, ApplicationClaims, $route, $q) {
|
module.factory('ClientClaimsLoader', function(Loader, ClientClaims, $route, $q) {
|
||||||
return Loader.get(ApplicationClaims, function() {
|
return Loader.get(ClientClaims, function() {
|
||||||
return {
|
return {
|
||||||
realm : $route.current.params.realm,
|
realm : $route.current.params.realm,
|
||||||
application : $route.current.params.application
|
client : $route.current.params.client
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
module.factory('ApplicationInstallationLoader', function(Loader, ApplicationInstallation, $route, $q) {
|
module.factory('ClientInstallationLoader', function(Loader, ClientInstallation, $route, $q) {
|
||||||
return Loader.get(ApplicationInstallation, function() {
|
return Loader.get(ClientInstallation, function() {
|
||||||
return {
|
return {
|
||||||
realm : $route.current.params.realm,
|
realm : $route.current.params.realm,
|
||||||
application : $route.current.params.application
|
client : $route.current.params.client
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
module.factory('ApplicationRoleListLoader', function(Loader, ApplicationRole, $route, $q) {
|
module.factory('ClientRoleListLoader', function(Loader, ClientRole, $route, $q) {
|
||||||
return Loader.query(ApplicationRole, function() {
|
return Loader.query(ClientRole, function() {
|
||||||
return {
|
return {
|
||||||
realm : $route.current.params.realm,
|
realm : $route.current.params.realm,
|
||||||
application : $route.current.params.application
|
client : $route.current.params.client
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
module.factory('ApplicationLoader', function(Loader, Application, $route, $q) {
|
module.factory('ClientLoader', function(Loader, Client, $route, $q) {
|
||||||
return Loader.get(Application, function() {
|
return Loader.get(Client, function() {
|
||||||
return {
|
return {
|
||||||
realm : $route.current.params.realm,
|
realm : $route.current.params.realm,
|
||||||
application : $route.current.params.application
|
client : $route.current.params.client
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
module.factory('ApplicationListLoader', function(Loader, Application, $route, $q) {
|
module.factory('ClientListLoader', function(Loader, Client, $route, $q) {
|
||||||
return Loader.query(Application, function() {
|
return Loader.query(Client, function() {
|
||||||
return {
|
return {
|
||||||
realm : $route.current.params.realm
|
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) {
|
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 Loader.query(RoleMapping, function() {
|
||||||
return {
|
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) {
|
module.factory('IdentityProviderLoader', function(Loader, IdentityProvider, $route, $q) {
|
||||||
return Loader.get(IdentityProvider, function () {
|
return Loader.get(IdentityProvider, function () {
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -190,10 +190,10 @@ module.factory('ServerInfo', function($resource) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
module.factory('ApplicationProtocolMapper', function($resource) {
|
module.factory('ClientProtocolMapper', function($resource) {
|
||||||
return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/protocol-mappers/models/:id', {
|
return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/protocol-mappers/models/:id', {
|
||||||
realm : '@realm',
|
realm : '@realm',
|
||||||
application: '@application',
|
client: '@client',
|
||||||
id : "@id"
|
id : "@id"
|
||||||
}, {
|
}, {
|
||||||
update : {
|
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) {
|
module.factory('User', function($resource) {
|
||||||
return $resource(authUrl + '/admin/realms/:realm/users/:userId', {
|
return $resource(authUrl + '/admin/realms/:realm/users/:userId', {
|
||||||
realm : '@realm',
|
realm : '@realm',
|
||||||
|
@ -347,72 +324,72 @@ module.factory('AvailableRealmRoleMapping', function($resource) {
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
module.factory('ApplicationRoleMapping', function($resource) {
|
module.factory('ClientRoleMapping', function($resource) {
|
||||||
return $resource(authUrl + '/admin/realms/:realm/users/:userId/role-mappings/applications-by-id/:application', {
|
return $resource(authUrl + '/admin/realms/:realm/users/:userId/role-mappings/clients-by-id/:client', {
|
||||||
realm : '@realm',
|
realm : '@realm',
|
||||||
userId : '@userId',
|
userId : '@userId',
|
||||||
application : "@application"
|
client : "@client"
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
module.factory('AvailableApplicationRoleMapping', function($resource) {
|
module.factory('AvailableClientRoleMapping', function($resource) {
|
||||||
return $resource(authUrl + '/admin/realms/:realm/users/:userId/role-mappings/applications-by-id/:application/available', {
|
return $resource(authUrl + '/admin/realms/:realm/users/:userId/role-mappings/clients-by-id/:client/available', {
|
||||||
realm : '@realm',
|
realm : '@realm',
|
||||||
userId : '@userId',
|
userId : '@userId',
|
||||||
application : "@application"
|
client : "@client"
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
module.factory('CompositeApplicationRoleMapping', function($resource) {
|
module.factory('CompositeClientRoleMapping', function($resource) {
|
||||||
return $resource(authUrl + '/admin/realms/:realm/users/:userId/role-mappings/applications-by-id/:application/composite', {
|
return $resource(authUrl + '/admin/realms/:realm/users/:userId/role-mappings/clients-by-id/:client/composite', {
|
||||||
realm : '@realm',
|
realm : '@realm',
|
||||||
userId : '@userId',
|
userId : '@userId',
|
||||||
application : "@application"
|
client : "@client"
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
module.factory('ApplicationRealmScopeMapping', function($resource) {
|
module.factory('ClientRealmScopeMapping', function($resource) {
|
||||||
return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/scope-mappings/realm', {
|
return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/scope-mappings/realm', {
|
||||||
realm : '@realm',
|
realm : '@realm',
|
||||||
application : '@application'
|
client : '@client'
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
module.factory('ApplicationAvailableRealmScopeMapping', function($resource) {
|
module.factory('ClientAvailableRealmScopeMapping', function($resource) {
|
||||||
return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/scope-mappings/realm/available', {
|
return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/scope-mappings/realm/available', {
|
||||||
realm : '@realm',
|
realm : '@realm',
|
||||||
application : '@application'
|
client : '@client'
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
module.factory('ApplicationCompositeRealmScopeMapping', function($resource) {
|
module.factory('ClientCompositeRealmScopeMapping', function($resource) {
|
||||||
return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/scope-mappings/realm/composite', {
|
return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/scope-mappings/realm/composite', {
|
||||||
realm : '@realm',
|
realm : '@realm',
|
||||||
application : '@application'
|
client : '@client'
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
module.factory('ApplicationApplicationScopeMapping', function($resource) {
|
module.factory('ClientClientScopeMapping', function($resource) {
|
||||||
return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/scope-mappings/applications-by-id/:targetApp', {
|
return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/scope-mappings/clients-by-id/:targetClient', {
|
||||||
realm : '@realm',
|
realm : '@realm',
|
||||||
application : '@application',
|
client : '@client',
|
||||||
targetApp : '@targetApp'
|
targetClient : '@targetClient'
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
module.factory('ApplicationAvailableApplicationScopeMapping', function($resource) {
|
module.factory('ClientAvailableClientScopeMapping', function($resource) {
|
||||||
return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/scope-mappings/applications-by-id/:targetApp/available', {
|
return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/scope-mappings/clients-by-id/:targetClient/available', {
|
||||||
realm : '@realm',
|
realm : '@realm',
|
||||||
application : '@application',
|
client : '@client',
|
||||||
targetApp : '@targetApp'
|
targetClient : '@targetClient'
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
module.factory('ApplicationCompositeApplicationScopeMapping', function($resource) {
|
module.factory('ClientCompositeClientScopeMapping', function($resource) {
|
||||||
return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/scope-mappings/applications-by-id/:targetApp/composite', {
|
return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/scope-mappings/clients-by-id/:targetClient/composite', {
|
||||||
realm : '@realm',
|
realm : '@realm',
|
||||||
application : '@application',
|
client : '@client',
|
||||||
targetApp : '@targetApp'
|
targetClient : '@targetClient'
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -443,24 +420,24 @@ module.factory('RealmSessionStats', function($resource) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
module.factory('RealmApplicationSessionStats', function($resource) {
|
module.factory('RealmClientSessionStats', function($resource) {
|
||||||
return $resource(authUrl + '/admin/realms/:realm/application-by-id-session-stats', {
|
return $resource(authUrl + '/admin/realms/:realm/client-by-id-session-stats', {
|
||||||
realm : '@realm'
|
realm : '@realm'
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
module.factory('RoleApplicationComposites', function($resource) {
|
module.factory('RoleClientComposites', function($resource) {
|
||||||
return $resource(authUrl + '/admin/realms/:realm/roles-by-id/:role/composites/applications-by-id/:application', {
|
return $resource(authUrl + '/admin/realms/:realm/roles-by-id/:role/composites/clients-by-id/:client', {
|
||||||
realm : '@realm',
|
realm : '@realm',
|
||||||
role : '@role',
|
role : '@role',
|
||||||
application : "@application"
|
client : "@client"
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
function roleControl($scope, realm, role, roles, applications,
|
function roleControl($scope, realm, role, roles, clients,
|
||||||
ApplicationRole, RoleById, RoleRealmComposites, RoleApplicationComposites,
|
ClientRole, RoleById, RoleRealmComposites, RoleClientComposites,
|
||||||
$http, $location, Notifications, Dialog) {
|
$http, $location, Notifications, Dialog) {
|
||||||
|
|
||||||
$scope.$watch(function () {
|
$scope.$watch(function () {
|
||||||
|
@ -499,11 +476,11 @@ function roleControl($scope, realm, role, roles, applications,
|
||||||
$scope.selectedRealmRoles = [];
|
$scope.selectedRealmRoles = [];
|
||||||
$scope.selectedRealmMappings = [];
|
$scope.selectedRealmMappings = [];
|
||||||
$scope.realmMappings = [];
|
$scope.realmMappings = [];
|
||||||
$scope.applications = applications;
|
$scope.clients = clients;
|
||||||
$scope.applicationRoles = [];
|
$scope.clientRoles = [];
|
||||||
$scope.selectedApplicationRoles = [];
|
$scope.selectedClientRoles = [];
|
||||||
$scope.selectedApplicationMappings = [];
|
$scope.selectedClientMappings = [];
|
||||||
$scope.applicationMappings = [];
|
$scope.clientMappings = [];
|
||||||
|
|
||||||
for (var j = 0; j < $scope.realmRoles.length; j++) {
|
for (var j = 0; j < $scope.realmRoles.length; j++) {
|
||||||
if ($scope.realmRoles[j].id == role.id) {
|
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;
|
$scope.compositeSwitchDisabled=true;
|
||||||
$http.post(authUrl + '/admin/realms/' + realm.realm + '/roles-by-id/' + role.id + '/composites',
|
$http.post(authUrl + '/admin/realms/' + realm.realm + '/roles-by-id/' + role.id + '/composites',
|
||||||
$scope.selectedApplicationRoles).success(function() {
|
$scope.selectedClientRoles).success(function() {
|
||||||
for (var i = 0; i < $scope.selectedApplicationRoles.length; i++) {
|
for (var i = 0; i < $scope.selectedClientRoles.length; i++) {
|
||||||
var role = $scope.selectedApplicationRoles[i];
|
var role = $scope.selectedClientRoles[i];
|
||||||
var idx = $scope.applicationRoles.indexOf($scope.selectedApplicationRoles[i]);
|
var idx = $scope.clientRoles.indexOf($scope.selectedClientRoles[i]);
|
||||||
if (idx != -1) {
|
if (idx != -1) {
|
||||||
$scope.applicationRoles.splice(idx, 1);
|
$scope.clientRoles.splice(idx, 1);
|
||||||
$scope.applicationMappings.push(role);
|
$scope.clientMappings.push(role);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$scope.selectedApplicationRoles = [];
|
$scope.selectedClientRoles = [];
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.deleteApplicationRole = function() {
|
$scope.deleteClientRole = function() {
|
||||||
$scope.compositeSwitchDisabled=true;
|
$scope.compositeSwitchDisabled=true;
|
||||||
$http.delete(authUrl + '/admin/realms/' + realm.realm + '/roles-by-id/' + role.id + '/composites',
|
$http.delete(authUrl + '/admin/realms/' + realm.realm + '/roles-by-id/' + role.id + '/composites',
|
||||||
{data : $scope.selectedApplicationMappings, headers : {"content-type" : "application/json"}}).success(function() {
|
{data : $scope.selectedClientMappings, headers : {"content-type" : "application/json"}}).success(function() {
|
||||||
for (var i = 0; i < $scope.selectedApplicationMappings.length; i++) {
|
for (var i = 0; i < $scope.selectedClientMappings.length; i++) {
|
||||||
var role = $scope.selectedApplicationMappings[i];
|
var role = $scope.selectedClientMappings[i];
|
||||||
var idx = $scope.applicationMappings.indexOf($scope.selectedApplicationMappings[i]);
|
var idx = $scope.clientMappings.indexOf($scope.selectedClientMappings[i]);
|
||||||
if (idx != -1) {
|
if (idx != -1) {
|
||||||
$scope.applicationMappings.splice(idx, 1);
|
$scope.clientMappings.splice(idx, 1);
|
||||||
$scope.applicationRoles.push(role);
|
$scope.clientRoles.push(role);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$scope.selectedApplicationMappings = [];
|
$scope.selectedClientMappings = [];
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
$scope.changeApplication = function() {
|
$scope.changeClient = function() {
|
||||||
$scope.applicationRoles = ApplicationRole.query({realm : realm.realm, application : $scope.compositeApp.id}, function() {
|
$scope.clientRoles = ClientRole.query({realm : realm.realm, client : $scope.compositeClient.id}, function() {
|
||||||
$scope.applicationMappings = RoleApplicationComposites.query({realm : realm.realm, role : role.id, application : $scope.compositeApp.id}, function(){
|
$scope.clientMappings = RoleClientComposites.query({realm : realm.realm, role : role.id, client : $scope.compositeClient.id}, function(){
|
||||||
for (var i = 0; i < $scope.applicationMappings.length; i++) {
|
for (var i = 0; i < $scope.clientMappings.length; i++) {
|
||||||
var role = $scope.applicationMappings[i];
|
var role = $scope.clientMappings[i];
|
||||||
for (var j = 0; j < $scope.applicationRoles.length; j++) {
|
for (var j = 0; j < $scope.clientRoles.length; j++) {
|
||||||
var realmRole = $scope.applicationRoles[j];
|
var realmRole = $scope.clientRoles[j];
|
||||||
if (realmRole.id == role.id) {
|
if (realmRole.id == role.id) {
|
||||||
var idx = $scope.applicationRoles.indexOf(realmRole);
|
var idx = $scope.clientRoles.indexOf(realmRole);
|
||||||
if (idx != -1) {
|
if (idx != -1) {
|
||||||
$scope.applicationRoles.splice(idx, 1);
|
$scope.clientRoles.splice(idx, 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
for (var j = 0; j < $scope.applicationRoles.length; j++) {
|
for (var j = 0; j < $scope.clientRoles.length; j++) {
|
||||||
if ($scope.applicationRoles[j] == role.id) {
|
if ($scope.clientRoles[j] == role.id) {
|
||||||
var appRole = $scope.applicationRoles[j];
|
var appRole = $scope.clientRoles[j];
|
||||||
var idx = $scope.applicationRoles.indexof(appRole);
|
var idx = $scope.clientRoles.indexof(appRole);
|
||||||
$scope.applicationRoles.splice(idx, 1);
|
$scope.clientRoles.splice(idx, 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -653,10 +630,10 @@ module.factory('RoleById', function($resource) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
module.factory('ApplicationRole', function($resource) {
|
module.factory('ClientRole', function($resource) {
|
||||||
return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/roles/:role', {
|
return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/roles/:role', {
|
||||||
realm : '@realm',
|
realm : '@realm',
|
||||||
application : "@application",
|
client : "@client",
|
||||||
role : '@role'
|
role : '@role'
|
||||||
}, {
|
}, {
|
||||||
update : {
|
update : {
|
||||||
|
@ -665,10 +642,10 @@ module.factory('ApplicationRole', function($resource) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
module.factory('ApplicationClaims', function($resource) {
|
module.factory('ClientClaims', function($resource) {
|
||||||
return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/claims', {
|
return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/claims', {
|
||||||
realm : '@realm',
|
realm : '@realm',
|
||||||
application : "@application"
|
client : "@client"
|
||||||
}, {
|
}, {
|
||||||
update : {
|
update : {
|
||||||
method : 'PUT'
|
method : 'PUT'
|
||||||
|
@ -676,52 +653,52 @@ module.factory('ApplicationClaims', function($resource) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
module.factory('ApplicationProtocolMappersByProtocol', function($resource) {
|
module.factory('ClientProtocolMappersByProtocol', function($resource) {
|
||||||
return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/protocol-mappers/protocol/:protocol', {
|
return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/protocol-mappers/protocol/:protocol', {
|
||||||
realm : '@realm',
|
realm : '@realm',
|
||||||
application : "@application",
|
client : "@client",
|
||||||
protocol : "@protocol"
|
protocol : "@protocol"
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
module.factory('ApplicationSessionStats', function($resource) {
|
module.factory('ClientSessionStats', function($resource) {
|
||||||
return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/session-stats', {
|
return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/session-stats', {
|
||||||
realm : '@realm',
|
realm : '@realm',
|
||||||
application : "@application"
|
client : "@client"
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
module.factory('ApplicationSessionStatsWithUsers', function($resource) {
|
module.factory('ClientSessionStatsWithUsers', function($resource) {
|
||||||
return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/session-stats?users=true', {
|
return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/session-stats?users=true', {
|
||||||
realm : '@realm',
|
realm : '@realm',
|
||||||
application : "@application"
|
client : "@client"
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
module.factory('ApplicationSessionCount', function($resource) {
|
module.factory('ClientSessionCount', function($resource) {
|
||||||
return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/session-count', {
|
return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/session-count', {
|
||||||
realm : '@realm',
|
realm : '@realm',
|
||||||
application : "@application"
|
client : "@client"
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
module.factory('ApplicationUserSessions', function($resource) {
|
module.factory('ClientUserSessions', function($resource) {
|
||||||
return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/user-sessions', {
|
return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/user-sessions', {
|
||||||
realm : '@realm',
|
realm : '@realm',
|
||||||
application : "@application"
|
client : "@client"
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
module.factory('ApplicationLogoutAll', function($resource) {
|
module.factory('ClientLogoutAll', function($resource) {
|
||||||
return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/logout-all', {
|
return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/logout-all', {
|
||||||
realm : '@realm',
|
realm : '@realm',
|
||||||
application : "@application"
|
client : "@client"
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
module.factory('ApplicationLogoutUser', function($resource) {
|
module.factory('ClientLogoutUser', function($resource) {
|
||||||
return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/logout-user/:user', {
|
return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/logout-user/:user', {
|
||||||
realm : '@realm',
|
realm : '@realm',
|
||||||
application : "@application",
|
client : "@client",
|
||||||
user : "@user"
|
user : "@user"
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -731,39 +708,39 @@ module.factory('RealmLogoutAll', function($resource) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
module.factory('ApplicationPushRevocation', function($resource) {
|
module.factory('ClientPushRevocation', function($resource) {
|
||||||
return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/push-revocation', {
|
return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/push-revocation', {
|
||||||
realm : '@realm',
|
realm : '@realm',
|
||||||
application : "@application"
|
client : "@client"
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
module.factory('ApplicationClusterNode', function($resource) {
|
module.factory('ClientClusterNode', function($resource) {
|
||||||
return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/nodes/:node', {
|
return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/nodes/:node', {
|
||||||
realm : '@realm',
|
realm : '@realm',
|
||||||
application : "@application"
|
client : "@client"
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
module.factory('ApplicationTestNodesAvailable', function($resource) {
|
module.factory('ClientTestNodesAvailable', function($resource) {
|
||||||
return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/test-nodes-available', {
|
return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/test-nodes-available', {
|
||||||
realm : '@realm',
|
realm : '@realm',
|
||||||
application : "@application"
|
client : "@client"
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
module.factory('ApplicationCertificate', function($resource) {
|
module.factory('ClientCertificate', function($resource) {
|
||||||
return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/certificates/:attribute', {
|
return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/certificates/:attribute', {
|
||||||
realm : '@realm',
|
realm : '@realm',
|
||||||
application : "@application",
|
client : "@client",
|
||||||
attribute: "@attribute"
|
attribute: "@attribute"
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
module.factory('ApplicationCertificateGenerate', function($resource) {
|
module.factory('ClientCertificateGenerate', function($resource) {
|
||||||
return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/certificates/:attribute/generate', {
|
return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/certificates/:attribute/generate', {
|
||||||
realm : '@realm',
|
realm : '@realm',
|
||||||
application : "@application",
|
client : "@client",
|
||||||
attribute: "@attribute"
|
attribute: "@attribute"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -773,10 +750,10 @@ module.factory('ApplicationCertificateGenerate', function($resource) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
module.factory('ApplicationCertificateDownload', function($resource) {
|
module.factory('ClientCertificateDownload', function($resource) {
|
||||||
return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/certificates/:attribute/download', {
|
return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/certificates/:attribute/download', {
|
||||||
realm : '@realm',
|
realm : '@realm',
|
||||||
application : "@application",
|
client : "@client",
|
||||||
attribute: "@attribute"
|
attribute: "@attribute"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -787,10 +764,10 @@ module.factory('ApplicationCertificateDownload', function($resource) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
module.factory('Application', function($resource) {
|
module.factory('Client', function($resource) {
|
||||||
return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application', {
|
return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client', {
|
||||||
realm : '@realm',
|
realm : '@realm',
|
||||||
application : '@application'
|
client : '@client'
|
||||||
}, {
|
}, {
|
||||||
update : {
|
update : {
|
||||||
method : 'PUT'
|
method : 'PUT'
|
||||||
|
@ -798,29 +775,29 @@ module.factory('Application', function($resource) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
module.factory('ApplicationInstallation', function($resource) {
|
module.factory('ClientInstallation', function($resource) {
|
||||||
var url = authUrl + '/admin/realms/:realm/applications-by-id/:application/installation/json';
|
var url = authUrl + '/admin/realms/:realm/clients-by-id/:client/installation/json';
|
||||||
return {
|
return {
|
||||||
url : function(parameters)
|
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) {
|
module.factory('ClientInstallationJBoss', function($resource) {
|
||||||
var url = authUrl + '/admin/realms/:realm/applications-by-id/:application/installation/jboss';
|
var url = authUrl + '/admin/realms/:realm/clients-by-id/:client/installation/jboss';
|
||||||
return {
|
return {
|
||||||
url : function(parameters)
|
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) {
|
module.factory('ClientCredentials', function($resource) {
|
||||||
return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/client-secret', {
|
return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/client-secret', {
|
||||||
realm : '@realm',
|
realm : '@realm',
|
||||||
application : '@application'
|
client : '@client'
|
||||||
}, {
|
}, {
|
||||||
update : {
|
update : {
|
||||||
method : 'POST'
|
method : 'POST'
|
||||||
|
@ -828,10 +805,10 @@ module.factory('ApplicationCredentials', function($resource) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
module.factory('ApplicationOrigins', function($resource) {
|
module.factory('ClientOrigins', function($resource) {
|
||||||
return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/allowed-origins', {
|
return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/allowed-origins', {
|
||||||
realm : '@realm',
|
realm : '@realm',
|
||||||
application : '@application'
|
client : '@client'
|
||||||
}, {
|
}, {
|
||||||
update : {
|
update : {
|
||||||
method : 'PUT',
|
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) {
|
module.factory('Current', function(Realm, $route) {
|
||||||
var current = {};
|
var current = {};
|
||||||
|
|
||||||
current.realms = {};
|
current.realms = {};
|
||||||
current.realm = null;
|
current.realm = null;
|
||||||
current.applications = {};
|
current.clients = {};
|
||||||
current.application = null;
|
current.client = null;
|
||||||
|
|
||||||
current.refresh = function() {
|
current.refresh = function() {
|
||||||
current.realm = null;
|
current.realm = null;
|
||||||
|
|
|
@ -1,59 +0,0 @@
|
||||||
<div class="bs-sidebar col-md-3 clearfix" data-ng-include data-src="resourceUrl + '/partials/realm-menu.html'"></div>
|
|
||||||
<div id="content-area" class="col-md-9" role="main">
|
|
||||||
<h2></h2>
|
|
||||||
<div id="content">
|
|
||||||
<h2><span>{{realm.realm}}</span> Applications <span tooltip-placement="right" tooltip="Applications are trusted browser apps and web services in a realm. These applications can request a login. You can also define application specific roles." class="fa fa-info-circle"></span></h2>
|
|
||||||
<table class="table table-striped table-bordered">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th class="kc-table-actions" colspan="3">
|
|
||||||
<div class="search-comp clearfix">
|
|
||||||
<input type="text" placeholder="Search..." class="form-control search" data-ng-model="search.name"
|
|
||||||
onkeyup="if(event.keyCode == 13){$(this).next('button').click();}">
|
|
||||||
<button type="submit" class="kc-icon-search" tooltip-placement="right"
|
|
||||||
tooltip="Search by application name.">
|
|
||||||
Icon: search
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class="pull-right">
|
|
||||||
<a class="btn btn-primary" href="#/import/application/{{realm.realm}}" data-ng-show="importButton">Import</a>
|
|
||||||
<a class="btn btn-primary" href="#/create/application/{{realm.realm}}">Create</a>
|
|
||||||
</div>
|
|
||||||
</th>
|
|
||||||
</tr>
|
|
||||||
<tr data-ng-hide="applications.length == 0">
|
|
||||||
<th>Application Name</th>
|
|
||||||
<th>Enabled</th>
|
|
||||||
<th>Base URL</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<!--<tfoot data-ng-show="applications && applications.length > 5">
|
|
||||||
<tr>
|
|
||||||
<td colspan="3">
|
|
||||||
<div class="table-nav">
|
|
||||||
<a href="#" class="first disabled">First page</a><a href="#" class="prev disabled">Previous
|
|
||||||
page</a><span><strong>1-8</strong> of <strong>10</strong></span><a href="#"
|
|
||||||
class="next">Next
|
|
||||||
page</a><a href="#" class="last">Last page</a>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tfoot>-->
|
|
||||||
<tbody>
|
|
||||||
<tr ng-repeat="app in applications | filter:search">
|
|
||||||
<td><a href="#/realms/{{realm.realm}}/applications/{{app.id}}">{{app.name}}</a></td>
|
|
||||||
<td>{{app.enabled}}</td>
|
|
||||||
<td ng-class="{'text-muted': !app.baseUrl}">
|
|
||||||
<a href="{{app.baseUrl}}" data-ng-show="app.baseUrl">{{app.baseUrl}}</a>
|
|
||||||
<span data-ng-hide="app.baseUrl">Not defined</span>
|
|
||||||
</tr>
|
|
||||||
<tr data-ng-show="applications.length == 0">
|
|
||||||
<td>No applications available</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<div class="feedback warning inline" data-ng-show="search && applications.length == 0">
|
|
||||||
<p><strong>Your search returned no results.</strong><br>Try modifying the query and try again.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
|
@ -1,47 +0,0 @@
|
||||||
<div class="bs-sidebar col-md-3 clearfix" data-ng-include data-src="resourceUrl + '/partials/realm-menu.html'"></div>
|
|
||||||
<div id="content-area" class="col-md-9" role="main">
|
|
||||||
<kc-navigation-application></kc-navigation-application>
|
|
||||||
<div id="content">
|
|
||||||
<ol class="breadcrumb" data-ng-hide="create">
|
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications">Applications</a></li>
|
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.id}}">{{application.name}}</a></li>
|
|
||||||
<li class="active">Protocol Mappers</li>
|
|
||||||
</ol>
|
|
||||||
<h2><span>{{realm.realm}} </span> {{application.name}} {{application.protocol}} Protocol Mappers <span tooltip-placement="right" tooltip="Protocol mappers perform transformation on tokens and documents. They an do things like map user data into protocol claims, or just transform any requests going between the application and auth server." class="fa fa-info-circle"></span></h2>
|
|
||||||
<table class="table table-striped table-bordered">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th class="kc-table-actions" colspan="4">
|
|
||||||
<div class="search-comp clearfix">
|
|
||||||
<input type="text" placeholder="Search..." class="form-control search" data-ng-model="search.name"
|
|
||||||
onkeyup="if(event.keyCode == 13){$(this).next('button').click();}">
|
|
||||||
<button type="submit" class="kc-icon-search" tooltip-placement="right"
|
|
||||||
tooltip="Search by mapper name.">
|
|
||||||
Icon: search
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class="pull-right">
|
|
||||||
<a class="btn btn-primary" href="#/create/application/{{realm.realm}}/{{application.id}}/mappers">Create</a>
|
|
||||||
<a class="btn btn-primary" href="#/realms/{{realm.realm}}/applications/{{application.id}}/add-mappers">Add Builtin</a>
|
|
||||||
</div>
|
|
||||||
</th>
|
|
||||||
</tr>
|
|
||||||
<tr data-ng-hide="mappers.length == 0">
|
|
||||||
<th>Name</th>
|
|
||||||
<th>Category</th>
|
|
||||||
<th>Type</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr ng-repeat="mapper in mappers | filter:search">
|
|
||||||
<td><a href="#/realms/{{realm.realm}}/applications/{{application.id}}/mappers/{{mapper.id}}">{{mapper.name}}</a></td>
|
|
||||||
<td>{{mapperTypes[mapper.protocolMapper].category}}</td>
|
|
||||||
<td>{{mapperTypes[mapper.protocolMapper].name}}</td>
|
|
||||||
</tr>
|
|
||||||
<tr data-ng-show="mappers.length == 0">
|
|
||||||
<td>No mappers available</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
|
@ -1,16 +1,16 @@
|
||||||
<div class="bs-sidebar col-md-3 clearfix" data-ng-include data-src="resourceUrl + '/partials/realm-menu.html'"></div>
|
<div class="bs-sidebar col-md-3 clearfix" data-ng-include data-src="resourceUrl + '/partials/realm-menu.html'"></div>
|
||||||
<div id="content-area" class="col-md-9" role="main">
|
<div id="content-area" class="col-md-9" role="main">
|
||||||
<kc-navigation-application></kc-navigation-application>
|
<kc-navigation-client></kc-navigation-client>
|
||||||
<div id="content">
|
<div id="content">
|
||||||
<ol class="breadcrumb">
|
<ol class="breadcrumb">
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications">Applications</a></li>
|
<li><a href="#/realms/{{realm.realm}}/clients">Clients</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.id}}">{{application.name}}</a></li>
|
<li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}">{{client.clientId}}</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.id}}/clustering">Clustering</a></li>
|
<li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/clustering">Clustering</a></li>
|
||||||
<li class="active">{{node.host}}</li>
|
<li class="active">{{node.host}}</li>
|
||||||
</ol>
|
</ol>
|
||||||
<h2 data-ng-show="create || registered"><span>{{application.name}} Clustering</span></h2>
|
<h2 data-ng-show="create || registered"><span>{{client.clientId}} Clustering</span></h2>
|
||||||
<h2 data-ng-hide="create || registered">Cluster node on host <span>{{node.host}}</span> not registered!</h2>
|
<h2 data-ng-hide="create || registered">Cluster node on host <span>{{node.host}}</span> not registered!</h2>
|
||||||
<form class="form-horizontal" name="clusteringForm" novalidate kc-read-only="!access.manageApplications" data-ng-show="create || registered">
|
<form class="form-horizontal" name="clusteringForm" novalidate kc-read-only="!access.manageClients" data-ng-show="create || registered">
|
||||||
<fieldset >
|
<fieldset >
|
||||||
<legend><span class="text">Configuration of cluster node</span></legend>
|
<legend><span class="text">Configuration of cluster node</span></legend>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
|
@ -1,14 +1,14 @@
|
||||||
<div class="bs-sidebar col-md-3 clearfix" data-ng-include data-src="resourceUrl + '/partials/realm-menu.html'"></div>
|
<div class="bs-sidebar col-md-3 clearfix" data-ng-include data-src="resourceUrl + '/partials/realm-menu.html'"></div>
|
||||||
<div id="content-area" class="col-md-9" role="main">
|
<div id="content-area" class="col-md-9" role="main">
|
||||||
<kc-navigation-application></kc-navigation-application>
|
<kc-navigation-client></kc-navigation-client>
|
||||||
<div id="content">
|
<div id="content">
|
||||||
<ol class="breadcrumb" data-ng-hide="create">
|
<ol class="breadcrumb" data-ng-hide="create">
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications">Applications</a></li>
|
<li><a href="#/realms/{{realm.realm}}/clients">Clients</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.id}}">{{application.name}}</a></li>
|
<li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}">{{client.clientId}}</a></li>
|
||||||
<li class="active">Clustering</li>
|
<li class="active">Clustering</li>
|
||||||
</ol>
|
</ol>
|
||||||
<h2 data-ng-hide="create"><span>{{application.name}}</span> Clustering</h2>
|
<h2 data-ng-hide="create"><span>{{client.clientId}}</span> Clustering</h2>
|
||||||
<form class="form-horizontal" name="clusteringForm" novalidate kc-read-only="!access.manageApplications">
|
<form class="form-horizontal" name="clusteringForm" novalidate kc-read-only="!access.manageClients">
|
||||||
<legend><span class="text">Basic configuration</span></legend>
|
<legend><span class="text">Basic configuration</span></legend>
|
||||||
<fieldset >
|
<fieldset >
|
||||||
<div class="form-group clearfix">
|
<div class="form-group clearfix">
|
||||||
|
@ -17,12 +17,12 @@
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-4">
|
<div class="col-sm-4">
|
||||||
<input class="form-control" type="number" required
|
<input class="form-control" type="number" required
|
||||||
max="31536000" data-ng-model="application.nodeReRegistrationTimeout"
|
max="31536000" data-ng-model="client.nodeReRegistrationTimeout"
|
||||||
id="nodeReRegistrationTimeout" name="nodeReRegistrationTimeout"/>
|
id="nodeReRegistrationTimeout" name="nodeReRegistrationTimeout"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-4 select-kc">
|
<div class="col-sm-4 select-kc">
|
||||||
<select name="nodeReRegistrationTimeoutUnit" data-ng-model="application.nodeReRegistrationTimeoutUnit" >
|
<select name="nodeReRegistrationTimeoutUnit" data-ng-model="client.nodeReRegistrationTimeoutUnit" >
|
||||||
<option data-ng-selected="!application.nodeReRegistrationTimeoutUnit">Seconds</option>
|
<option data-ng-selected="!client.nodeReRegistrationTimeoutUnit">Seconds</option>
|
||||||
<option>Minutes</option>
|
<option>Minutes</option>
|
||||||
<option>Hours</option>
|
<option>Hours</option>
|
||||||
<option>Days</option>
|
<option>Days</option>
|
||||||
|
@ -30,7 +30,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<span tooltip-placement="right" tooltip="Interval to specify max time for registered application cluster nodes to re-register. If cluster node won't send re-registration request to Keycloak within this time, it will be unregistered from Keycloak" class="fa fa-info-circle"></span>
|
<span tooltip-placement="right" tooltip="Interval to specify max time for registered clients cluster nodes to re-register. If cluster node won't send re-registration request to Keycloak within this time, it will be unregistered from Keycloak" class="fa fa-info-circle"></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="pull-right form-actions" data-ng-show="access.manageRealm">
|
<div class="pull-right form-actions" data-ng-show="access.manageRealm">
|
||||||
<button data-kc-reset data-ng-show="changed">Clear changes</button>
|
<button data-kc-reset data-ng-show="changed">Clear changes</button>
|
||||||
|
@ -43,10 +43,10 @@
|
||||||
<table class="table table-striped table-bordered">
|
<table class="table table-striped table-bordered">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th class="kc-table-actions" colspan="3" data-ng-show="access.manageApplications">
|
<th class="kc-table-actions" colspan="3" data-ng-show="access.manageClients">
|
||||||
<div class="pull-right">
|
<div class="pull-right">
|
||||||
<a class="btn btn-primary" tooltip="Manually register cluster node. This is usually not needed as cluster node should be registered automatically by adapter"
|
<a class="btn btn-primary" tooltip="Manually register cluster node. This is usually not needed as cluster node should be registered automatically by adapter"
|
||||||
tooltip-placement="bottom" href="#/register-node/realms/{{realm.realm}}/applications/{{application.id}}/clustering">Register node manually</a>
|
tooltip-placement="bottom" href="#/register-node/realms/{{realm.realm}}/clients/{{client.id}}/clustering">Register node manually</a>
|
||||||
</div>
|
</div>
|
||||||
</th>
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -57,7 +57,7 @@
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr ng-repeat="node in nodeRegistrations">
|
<tr ng-repeat="node in nodeRegistrations">
|
||||||
<td><a href="#/realms/{{realm.realm}}/applications/{{application.id}}/clustering/{{node.host}}">{{node.host}}</a></td>
|
<td><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/clustering/{{node.host}}">{{node.host}}</a></td>
|
||||||
<td>{{node.lastRegistration}}</td>
|
<td>{{node.lastRegistration}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr data-ng-show="!nodeRegistrations || nodeRegistrations.length == 0">
|
<tr data-ng-show="!nodeRegistrations || nodeRegistrations.length == 0">
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue