keycloak-aplcache
Changes
model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/DefaultCacheRealmProvider.java 11(+11 -0)
model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/NoCacheRealmProvider.java 10(+10 -0)
model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoRealmProvider.java 21(+19 -2)
model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoRealmProviderFactory.java 5(+4 -1)
Details
diff --git a/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.2.0.Beta1.xml b/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.2.0.Beta1.xml
index 0de32d8..71fc2c4 100755
--- a/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.2.0.Beta1.xml
+++ b/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.2.0.Beta1.xml
@@ -5,14 +5,24 @@
<column name="ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
- <column name="PROTOCOL_CLAIM" type="VARCHAR(255)"/>
+ <column name="NAME" type="VARCHAR(255)"/>
<column name="PROTOCOL" type="VARCHAR(255)"/>
<column name="SOURCE" type="VARCHAR(255)"/>
<column name="PROTOCOL_MAPPER_NAME" type="VARCHAR(255)"/>
- <column name="SOURCE_ATTRIBUTE" type="VARCHAR(255)"/>
<column name="APPLIED_BY_DEFAULT" type="BOOLEAN(1)"/>
+ <column name="CONSENT_REQUIRED" type="BOOLEAN(1)"/>
+ <column name="CONSENT_TEXT" type="VARCHAR(255)"/>
<column name="REALM_ID" type="VARCHAR(36)"/>
</createTable>
+ <createTable tableName="PROTOCOL_MAPPER_CONFIG">
+ <column name="PROTOCOL_MAPPER_ID" type="VARCHAR(36)">
+ <constraints nullable="false"/>
+ </column>
+ <column name="VALUE" type="CLOB"/>
+ <column name="NAME" type="VARCHAR(255)">
+ <constraints nullable="false"/>
+ </column>
+ </createTable>
<createTable tableName="CLAIM_TYPE">
<column name="ID" type="VARCHAR(36)">
<constraints nullable="false"/>
@@ -80,11 +90,13 @@
<addPrimaryKey columnNames="INTERNAL_ID" constraintName="CONSTRAINT_2B" tableName="IDENTITY_PROVIDER"/>
<addPrimaryKey columnNames="IDENTITY_PROVIDER, USER_ID" constraintName="CONSTRAINT_40" tableName="FEDERATED_IDENTITY"/>
<addPrimaryKey columnNames="IDENTITY_PROVIDER_ID, NAME" constraintName="CONSTRAINT_D" tableName="IDENTITY_PROVIDER_CONFIG"/>
+ <addPrimaryKey columnNames="PROTOCOL_MAPPER_ID, NAME" constraintName="CONSTRAINT_PMConfig" tableName="PROTOCOL_MAPPER_CONFIG"/>
<addForeignKeyConstraint baseColumnNames="REALM_ID" baseTableName="IDENTITY_PROVIDER" constraintName="FK2B4EBC52AE5C3B34" deferrable="false" initiallyDeferred="false" onDelete="RESTRICT" onUpdate="RESTRICT" referencedColumnNames="ID" referencedTableName="REALM"/>
<addForeignKeyConstraint baseColumnNames="REALM_ID" baseTableName="CLAIM_TYPE" constraintName="FK_CT_REALM" deferrable="false" initiallyDeferred="false" onDelete="RESTRICT" onUpdate="RESTRICT" referencedColumnNames="ID" referencedTableName="REALM"/>
<addForeignKeyConstraint baseColumnNames="REALM_ID" baseTableName="PROTOCOL_MAPPER" constraintName="FK_PCM_REALM" deferrable="false" initiallyDeferred="false" onDelete="RESTRICT" onUpdate="RESTRICT" referencedColumnNames="ID" referencedTableName="REALM"/>
<addForeignKeyConstraint baseColumnNames="USER_ID" baseTableName="FEDERATED_IDENTITY" constraintName="FK404288B92EF007A6" deferrable="false" initiallyDeferred="false" onDelete="RESTRICT" onUpdate="RESTRICT" referencedColumnNames="ID" referencedTableName="USER_ENTITY"/>
<addForeignKeyConstraint baseColumnNames="IDENTITY_PROVIDER_ID" baseTableName="IDENTITY_PROVIDER_CONFIG" constraintName="FKDC4897CF864C4E43" deferrable="false" initiallyDeferred="false" onDelete="RESTRICT" onUpdate="RESTRICT" referencedColumnNames="INTERNAL_ID" referencedTableName="IDENTITY_PROVIDER"/>
+ <addForeignKeyConstraint baseColumnNames="PROTOCOL_MAPPER_ID" baseTableName="PROTOCOL_MAPPER_CONFIG" constraintName="FK_PMConfig" deferrable="false" initiallyDeferred="false" onDelete="RESTRICT" onUpdate="RESTRICT" referencedColumnNames="ID" referencedTableName="PROTOCOL_MAPPER"/>
<addForeignKeyConstraint baseColumnNames="INTERNAL_ID" baseTableName="CLIENT_ALLOWED_IDENTITY_PROVIDER" constraintName="FK_7CELWNIBJI49AVXSRTUF6XJ12" referencedColumnNames="INTERNAL_ID" referencedTableName="IDENTITY_PROVIDER"/>
<addUniqueConstraint columnNames="INTERNAL_ID,CLIENT_ID" constraintName="UK_7CAELWNIBJI49AVXSRTUF6XJ12" tableName="CLIENT_ALLOWED_IDENTITY_PROVIDER"/>
<addForeignKeyConstraint baseColumnNames="MAPPING_ID" baseTableName="CLIENT_PROTOCOL_MAPPER" constraintName="FK_CPCM" referencedColumnNames="ID" referencedTableName="PROTOCOL_MAPPER"/>
diff --git a/core/src/main/java/org/keycloak/representations/idm/ProtocolMapperRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/ProtocolMapperRepresentation.java
index e721941..4f132e1 100755
--- a/core/src/main/java/org/keycloak/representations/idm/ProtocolMapperRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/ProtocolMapperRepresentation.java
@@ -1,17 +1,21 @@
package org.keycloak.representations.idm;
+import java.util.HashMap;
+import java.util.Map;
+
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class ProtocolMapperRepresentation {
protected String id;
- protected String protocolClaim;
+ protected String name;
protected String protocol;
- protected String source;
- protected String sourceAttribute;
protected String protocolMapper;
protected boolean appliedByDefault;
+ protected boolean consentRequired;
+ protected String consentText;
+ protected Map<String, String> config = new HashMap<String, String>();
public String getId() {
@@ -22,12 +26,12 @@ public class ProtocolMapperRepresentation {
this.id = id;
}
- public String getProtocolClaim() {
- return protocolClaim;
+ public String getName() {
+ return name;
}
- public void setProtocolClaim(String protocolClaim) {
- this.protocolClaim = protocolClaim;
+ public void setName(String name) {
+ this.name = name;
}
public String getProtocol() {
@@ -38,14 +42,6 @@ public class ProtocolMapperRepresentation {
this.protocol = protocol;
}
- public String getSourceAttribute() {
- return sourceAttribute;
- }
-
- public void setSourceAttribute(String sourceAttribute) {
- this.sourceAttribute = sourceAttribute;
- }
-
public boolean isAppliedByDefault() {
return appliedByDefault;
}
@@ -54,14 +50,6 @@ public class ProtocolMapperRepresentation {
this.appliedByDefault = appliedByDefault;
}
- public String getSource() {
- return source;
- }
-
- public void setSource(String source) {
- this.source = source;
- }
-
public String getProtocolMapper() {
return protocolMapper;
}
@@ -69,4 +57,28 @@ public class ProtocolMapperRepresentation {
public void setProtocolMapper(String protocolMapper) {
this.protocolMapper = protocolMapper;
}
+
+ public Map<String, String> getConfig() {
+ return config;
+ }
+
+ public void setConfig(Map<String, String> config) {
+ this.config = config;
+ }
+
+ public boolean isConsentRequired() {
+ return consentRequired;
+ }
+
+ public void setConsentRequired(boolean consentRequired) {
+ this.consentRequired = consentRequired;
+ }
+
+ public String getConsentText() {
+ return consentText;
+ }
+
+ public void setConsentText(String consentText) {
+ this.consentText = consentText;
+ }
}
diff --git a/docbook/reference/en/en-US/modules/adapter-config.xml b/docbook/reference/en/en-US/modules/adapter-config.xml
index d4ef642..21cc77a 100755
--- a/docbook/reference/en/en-US/modules/adapter-config.xml
+++ b/docbook/reference/en/en-US/modules/adapter-config.xml
@@ -14,7 +14,7 @@
"use-resource-role-mappings" : false,
"enable-cors" : true,
"cors-max-age" : 1000,
- "cors-allowed-methods" : [ "POST", "PUT", "DELETE", "GET" ],
+ "cors-allowed-methods" : "POST, PUT, DELETE, GET",
"bearer-only" : false,
"enable-basic-auth" : false,
"expose-token" : true,
diff --git a/model/api/src/main/java/org/keycloak/models/entities/ProtocolMapperEntity.java b/model/api/src/main/java/org/keycloak/models/entities/ProtocolMapperEntity.java
index de8f793..13f4cfc 100755
--- a/model/api/src/main/java/org/keycloak/models/entities/ProtocolMapperEntity.java
+++ b/model/api/src/main/java/org/keycloak/models/entities/ProtocolMapperEntity.java
@@ -2,18 +2,21 @@ package org.keycloak.models.entities;
import org.keycloak.models.ProtocolMapperModel;
+import java.util.Map;
+
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class ProtocolMapperEntity {
protected String id;
- protected String protocolClaim;
+ protected String name;
protected String protocol;
- protected ProtocolMapperModel.Source source;
- protected String sourceAttribute;
protected String protocolMapper;
protected boolean appliedByDefault;
+ protected boolean consentRequired;
+ protected String consentText;
+ protected Map<String, String> config;
public String getId() {
return id;
@@ -23,12 +26,12 @@ public class ProtocolMapperEntity {
this.id = id;
}
- public String getProtocolClaim() {
- return protocolClaim;
+ public String getName() {
+ return name;
}
- public void setProtocolClaim(String protocolClaim) {
- this.protocolClaim = protocolClaim;
+ public void setName(String name) {
+ this.name = name;
}
public String getProtocol() {
@@ -39,22 +42,6 @@ public class ProtocolMapperEntity {
this.protocol = protocol;
}
- public ProtocolMapperModel.Source getSource() {
- return source;
- }
-
- public void setSource(ProtocolMapperModel.Source source) {
- this.source = source;
- }
-
- public String getSourceAttribute() {
- return sourceAttribute;
- }
-
- public void setSourceAttribute(String sourceAttribute) {
- this.sourceAttribute = sourceAttribute;
- }
-
public boolean isAppliedByDefault() {
return appliedByDefault;
}
@@ -70,4 +57,28 @@ public class ProtocolMapperEntity {
public void setProtocolMapper(String protocolMapper) {
this.protocolMapper = protocolMapper;
}
+
+ public Map<String, String> getConfig() {
+ return config;
+ }
+
+ public void setConfig(Map<String, String> config) {
+ this.config = config;
+ }
+
+ public boolean isConsentRequired() {
+ return consentRequired;
+ }
+
+ public void setConsentRequired(boolean consentRequired) {
+ this.consentRequired = consentRequired;
+ }
+
+ public String getConsentText() {
+ return consentText;
+ }
+
+ public void setConsentText(String consentText) {
+ this.consentText = consentText;
+ }
}
diff --git a/model/api/src/main/java/org/keycloak/models/entities/RealmEntity.java b/model/api/src/main/java/org/keycloak/models/entities/RealmEntity.java
index 7db0bac..b511a32 100755
--- a/model/api/src/main/java/org/keycloak/models/entities/RealmEntity.java
+++ b/model/api/src/main/java/org/keycloak/models/entities/RealmEntity.java
@@ -53,7 +53,7 @@ public class RealmEntity extends AbstractIdentifiableEntity {
private List<UserFederationProviderEntity> userFederationProviders = new ArrayList<UserFederationProviderEntity>();
private List<IdentityProviderEntity> identityProviders = new ArrayList<IdentityProviderEntity>();
private List<ClaimTypeEntity> claimTypes = new ArrayList<ClaimTypeEntity>();
- private List<ProtocolMapperEntity> claimMappings = new ArrayList<ProtocolMapperEntity>();
+ private List<ProtocolMapperEntity> protocolMappers = new ArrayList<ProtocolMapperEntity>();
private Map<String, String> browserSecurityHeaders = new HashMap<String, String>();
private Map<String, String> smtpConfig = new HashMap<String, String>();
@@ -401,12 +401,12 @@ public class RealmEntity extends AbstractIdentifiableEntity {
this.claimTypes = claimTypes;
}
- public List<ProtocolMapperEntity> getClaimMappings() {
- return claimMappings;
+ public List<ProtocolMapperEntity> getProtocolMappers() {
+ return protocolMappers;
}
- public void setClaimMappings(List<ProtocolMapperEntity> claimMappings) {
- this.claimMappings = claimMappings;
+ public void setProtocolMappers(List<ProtocolMapperEntity> protocolMappers) {
+ this.protocolMappers = protocolMappers;
}
}
diff --git a/model/api/src/main/java/org/keycloak/models/ProtocolMapperModel.java b/model/api/src/main/java/org/keycloak/models/ProtocolMapperModel.java
index 001bb96..f27a9ea 100755
--- a/model/api/src/main/java/org/keycloak/models/ProtocolMapperModel.java
+++ b/model/api/src/main/java/org/keycloak/models/ProtocolMapperModel.java
@@ -1,5 +1,7 @@
package org.keycloak.models;
+import java.util.Map;
+
/**
* Specifies a mapping from user data to a protocol claim assertion. If protocolMapper is set, this points
* to a @Provider that will perform the mapping. If you have this set, then no other attributes of this class need to be set.
@@ -10,21 +12,14 @@ package org.keycloak.models;
* @version $Revision: 1 $
*/
public class ProtocolMapperModel {
- public static enum Source {
- USER_MODEL,
- USER_ATTRIBUTE,
- USER_SESSION_NOTE,
- CLIENT_SESSION_NOTE
- }
-
protected String id;
protected String name;
- protected String protocolClaim;
protected String protocol;
- protected Source source;
- protected String sourceAttribute;
protected String protocolMapper;
+ protected boolean consentRequired;
+ protected String consentText;
protected boolean appliedByDefault;
+ protected Map<String, String> config;
public String getId() {
@@ -43,14 +38,6 @@ public class ProtocolMapperModel {
this.name = name;
}
- public String getProtocolClaim() {
- return protocolClaim;
- }
-
- public void setProtocolClaim(String protocolClaim) {
- this.protocolClaim = protocolClaim;
- }
-
public String getProtocol() {
return protocol;
}
@@ -59,14 +46,6 @@ public class ProtocolMapperModel {
this.protocol = protocol;
}
- public String getSourceAttribute() {
- return sourceAttribute;
- }
-
- public void setSourceAttribute(String sourceAttribute) {
- this.sourceAttribute = sourceAttribute;
- }
-
public boolean isAppliedByDefault() {
return appliedByDefault;
}
@@ -75,14 +54,6 @@ public class ProtocolMapperModel {
this.appliedByDefault = appliedByDefault;
}
- public Source getSource() {
- return source;
- }
-
- public void setSource(Source source) {
- this.source = source;
- }
-
public String getProtocolMapper() {
return protocolMapper;
}
@@ -91,6 +62,30 @@ public class ProtocolMapperModel {
this.protocolMapper = protocolMapper;
}
+ public boolean isConsentRequired() {
+ return consentRequired;
+ }
+
+ public void setConsentRequired(boolean consentRequired) {
+ this.consentRequired = consentRequired;
+ }
+
+ public String getConsentText() {
+ return consentText;
+ }
+
+ public void setConsentText(String consentText) {
+ this.consentText = consentText;
+ }
+
+ public Map<String, String> getConfig() {
+ return config;
+ }
+
+ public void setConfig(Map<String, String> config) {
+ this.config = config;
+ }
+
@Override
public boolean equals(Object o) {
if (this == o) return true;
diff --git a/model/api/src/main/java/org/keycloak/models/RealmListenerHelper.java b/model/api/src/main/java/org/keycloak/models/RealmListenerHelper.java
new file mode 100755
index 0000000..b7c074d
--- /dev/null
+++ b/model/api/src/main/java/org/keycloak/models/RealmListenerHelper.java
@@ -0,0 +1,31 @@
+package org.keycloak.models;
+
+import java.util.LinkedList;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class RealmListenerHelper {
+ protected LinkedList<RealmProvider.RealmCreationListener> list = new LinkedList<RealmProvider.RealmCreationListener>();
+
+ public void registerListener(RealmProvider.RealmCreationListener listener) {
+ synchronized (list) {
+ list.add(listener);
+ }
+ }
+
+ public void unregisterListener(RealmProvider.RealmCreationListener listener) {
+ synchronized (list) {
+ list.remove(listener);
+ }
+ }
+
+ public void executeCreationListeners(RealmModel realm) {
+ synchronized (list) {
+ for (RealmProvider.RealmCreationListener listener : list) {
+ listener.created(realm);
+ }
+ }
+ }
+}
diff --git a/model/api/src/main/java/org/keycloak/models/RealmProvider.java b/model/api/src/main/java/org/keycloak/models/RealmProvider.java
index 4ec3c87..2c04cc1 100755
--- a/model/api/src/main/java/org/keycloak/models/RealmProvider.java
+++ b/model/api/src/main/java/org/keycloak/models/RealmProvider.java
@@ -9,10 +9,16 @@ import java.util.List;
* @version $Revision: 1 $
*/
public interface RealmProvider extends Provider {
+ public interface RealmCreationListener {
+ void created(RealmModel realm);
+ }
+
// Note: The reason there are so many query methods here is for layering a cache on top of an persistent KeycloakSession
RealmModel createRealm(String name);
RealmModel createRealm(String id, String name);
+ void registerListener(RealmCreationListener listener);
+ void unregisterListener(RealmCreationListener listener);
RealmModel getRealm(String id);
RealmModel getRealmByName(String name);
diff --git a/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java b/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
index 5d0c582..69d5477 100755
--- a/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
+++ b/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
@@ -341,11 +341,14 @@ public class ModelToRepresentation {
ProtocolMapperRepresentation rep = new ProtocolMapperRepresentation();
rep.setId(model.getId());
rep.setProtocol(model.getProtocol());
- rep.setProtocolClaim(model.getProtocolClaim());
- rep.setSourceAttribute(model.getSourceAttribute());
- rep.setSource(model.getSource().name());
+ Map<String, String> config = new HashMap<String, String>();
+ config.putAll(model.getConfig());
+ rep.setConfig(config);
+ rep.setName(model.getName());
rep.setProtocolMapper(model.getProtocolMapper());
rep.setAppliedByDefault(model.isAppliedByDefault());
+ rep.setConsentText(model.getConsentText());
+ rep.setConsentRequired(model.isConsentRequired());
return rep;
}
diff --git a/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java b/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
index 6c41613..2fb49af 100755
--- a/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
+++ b/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
@@ -118,7 +118,7 @@ public class RepresentationToModel {
importIdentityProviders(rep, newRealm);
importClaimTypes(rep, newRealm);
- importProtocolClaimMappings(rep, newRealm);
+ importProtocolMappers(rep, newRealm);
if (rep.getApplications() != null) {
Map<String, ApplicationModel> appMap = createApplications(rep, newRealm);
@@ -772,10 +772,15 @@ public class RepresentationToModel {
}
}
- private static void importProtocolClaimMappings(RealmRepresentation rep, RealmModel newRealm) {
+ private static void importProtocolMappers(RealmRepresentation rep, RealmModel newRealm) {
if (rep.getProtocolClaimMappings() != null) {
+ // we make sure we don't recreate mappers that are automatically created by the protocol providers.
for (ProtocolMapperRepresentation representation : rep.getProtocolClaimMappings()) {
- newRealm.addProtocolMapper(toModel(representation));
+ if (representation.getId() == null || newRealm.getProtocolMapperById(representation.getId()) == null) {
+ newRealm.addProtocolMapper(toModel(representation));
+ } else {
+ newRealm.updateProtocolMapper(toModel(representation));
+ }
}
}
}
@@ -808,12 +813,13 @@ public class RepresentationToModel {
public static ProtocolMapperModel toModel(ProtocolMapperRepresentation rep) {
ProtocolMapperModel model = new ProtocolMapperModel();
model.setId(rep.getId());
+ model.setName(rep.getName());
model.setAppliedByDefault(rep.isAppliedByDefault());
- model.setSource(ProtocolMapperModel.Source.valueOf(rep.getSource()));
- model.setSourceAttribute(rep.getSourceAttribute());
+ model.setConsentRequired(rep.isConsentRequired());
+ model.setConsentText(rep.getConsentText());
model.setProtocol(rep.getProtocol());
- model.setProtocolClaim(rep.getProtocolClaim());
model.setProtocolMapper(rep.getProtocolMapper());
+ model.setConfig(rep.getConfig());
return model;
}
}
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/DefaultCacheRealmProvider.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/DefaultCacheRealmProvider.java
index a1d232e..9419c91 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/DefaultCacheRealmProvider.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/DefaultCacheRealmProvider.java
@@ -51,6 +51,17 @@ public class DefaultCacheRealmProvider implements CacheRealmProvider {
}
@Override
+ public void registerListener(RealmCreationListener listener) {
+ getDelegate().registerListener(listener);
+ }
+
+ @Override
+ public void unregisterListener(RealmCreationListener listener) {
+ getDelegate().unregisterListener(listener);
+
+ }
+
+ @Override
public boolean isEnabled() {
return cache.isEnabled();
}
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/NoCacheRealmProvider.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/NoCacheRealmProvider.java
index e7b1551..9896e51 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/NoCacheRealmProvider.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/NoCacheRealmProvider.java
@@ -39,6 +39,16 @@ public class NoCacheRealmProvider implements CacheRealmProvider {
}
@Override
+ public void registerListener(RealmCreationListener listener) {
+ getDelegate().registerListener(listener);
+ }
+
+ @Override
+ public void unregisterListener(RealmCreationListener listener) {
+ getDelegate().unregisterListener(listener);
+
+ }
+ @Override
public void registerRealmInvalidation(String id) {
}
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/ClientAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/ClientAdapter.java
index 9faace4..c06cdec 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/ClientAdapter.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/ClientAdapter.java
@@ -362,11 +362,16 @@ public abstract class ClientAdapter implements ClientModel {
for (ProtocolMapperEntity entity : this.entity.getProtocolMappers()) {
ProtocolMapperModel mapping = new ProtocolMapperModel();
mapping.setId(entity.getId());
+ mapping.setName(entity.getName());
mapping.setProtocol(entity.getProtocol());
- mapping.setProtocolClaim(entity.getProtocolClaim());
mapping.setAppliedByDefault(entity.isAppliedByDefault());
- mapping.setSource(ProtocolMapperModel.Source.valueOf(entity.getSource()));
- mapping.setSourceAttribute(entity.getSourceAttribute());
+ mapping.setConsentRequired(entity.isConsentRequired());
+ mapping.setConsentText(entity.getConsentText());
+ Map<String, String> config = new HashMap<String, String>();
+ if (entity.getConfig() != null) {
+ config.putAll(entity.getConfig());
+ }
+ mapping.setConfig(config);
mappings.add(mapping);
}
return mappings;
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ProtocolMapperEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ProtocolMapperEntity.java
index 59e077f..bd8bbe2 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ProtocolMapperEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ProtocolMapperEntity.java
@@ -1,14 +1,18 @@
package org.keycloak.models.jpa.entities;
+import javax.persistence.CollectionTable;
import javax.persistence.Column;
+import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
+import javax.persistence.MapKeyColumn;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
+import java.util.Map;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@@ -25,18 +29,25 @@ public class ProtocolMapperEntity {
@Column(name="ID", length = 36)
protected String id;
- @Column(name = "PROTOCOL_CLAIM")
- protected String protocolClaim;
+ @Column(name="NAME")
+ protected String name;
+
@Column(name = "PROTOCOL")
protected String protocol;
- @Column(name = "SOURCE")
- protected String source;
- @Column(name = "SOURCE_ATTRIBUTE")
- protected String sourceAttribute;
@Column(name = "PROTOCOL_MAPPER_NAME")
protected String protocolMapper;
@Column(name = "APPLIED_BY_DEFAULT")
protected boolean appliedByDefault;
+ @Column(name="CONSENT_REQUIRED")
+ protected boolean consentRequired;
+ @Column(name="CONSENT_TEXT")
+ protected String consentText;
+
+ @ElementCollection
+ @MapKeyColumn(name="name")
+ @Column(name="value")
+ @CollectionTable(name="PROTOCOL_MAPPER_CONFIG", joinColumns={ @JoinColumn(name="PROTOCOL_MAPPER_ID") })
+ private Map<String, String> config;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "REALM_ID")
@@ -50,12 +61,12 @@ public class ProtocolMapperEntity {
this.id = id;
}
- public String getProtocolClaim() {
- return protocolClaim;
+ public String getName() {
+ return name;
}
- public void setProtocolClaim(String protocolClaim) {
- this.protocolClaim = protocolClaim;
+ public void setName(String name) {
+ this.name = name;
}
public String getProtocol() {
@@ -66,22 +77,6 @@ public class ProtocolMapperEntity {
this.protocol = protocol;
}
- public String getSource() {
- return source;
- }
-
- public void setSource(String source) {
- this.source = source;
- }
-
- public String getSourceAttribute() {
- return sourceAttribute;
- }
-
- public void setSourceAttribute(String sourceAttribute) {
- this.sourceAttribute = sourceAttribute;
- }
-
public String getProtocolMapper() {
return protocolMapper;
}
@@ -98,6 +93,14 @@ public class ProtocolMapperEntity {
this.appliedByDefault = appliedByDefault;
}
+ public Map<String, String> getConfig() {
+ return config;
+ }
+
+ public void setConfig(Map<String, String> config) {
+ this.config = config;
+ }
+
public RealmEntity getRealm() {
return realm;
}
@@ -106,6 +109,22 @@ public class ProtocolMapperEntity {
this.realm = realm;
}
+ public boolean isConsentRequired() {
+ return consentRequired;
+ }
+
+ public void setConsentRequired(boolean consentRequired) {
+ this.consentRequired = consentRequired;
+ }
+
+ public String getConsentText() {
+ return consentText;
+ }
+
+ public void setConsentText(String consentText) {
+ this.consentText = consentText;
+ }
+
@Override
public boolean equals(Object o) {
if (this == o) return true;
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaRealmProvider.java b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaRealmProvider.java
index 755fb6b..5529b83 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaRealmProvider.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaRealmProvider.java
@@ -3,6 +3,7 @@ package org.keycloak.models.jpa;
import org.keycloak.models.ApplicationModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.OAuthClientModel;
+import org.keycloak.models.RealmListenerHelper;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RealmProvider;
import org.keycloak.models.RoleModel;
@@ -25,10 +26,24 @@ import java.util.List;
public class JpaRealmProvider implements RealmProvider {
private final KeycloakSession session;
protected EntityManager em;
+ protected RealmListenerHelper listeners;
- public JpaRealmProvider(KeycloakSession session, EntityManager em) {
+
+ public JpaRealmProvider(KeycloakSession session, EntityManager em, RealmListenerHelper listeners) {
this.session = session;
this.em = em;
+ this.listeners = listeners;
+ }
+
+ @Override
+ public void registerListener(RealmCreationListener listener) {
+ listeners.registerListener(listener);
+ }
+
+ @Override
+ public void unregisterListener(RealmCreationListener listener) {
+ listeners.unregisterListener(listener);
+
}
@Override
@@ -43,7 +58,9 @@ public class JpaRealmProvider implements RealmProvider {
realm.setId(id);
em.persist(realm);
em.flush();
- return new RealmAdapter(session, em, realm);
+ RealmModel model = new RealmAdapter(session, em, realm);
+ listeners.executeCreationListeners(model);
+ return model;
}
@Override
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaRealmProviderFactory.java b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaRealmProviderFactory.java
index 7e090c2..4869ca7 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaRealmProviderFactory.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaRealmProviderFactory.java
@@ -3,6 +3,7 @@ package org.keycloak.models.jpa;
import org.keycloak.Config;
import org.keycloak.connections.jpa.JpaConnectionProvider;
import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmListenerHelper;
import org.keycloak.models.RealmProvider;
import org.keycloak.models.RealmProviderFactory;
@@ -14,6 +15,8 @@ import javax.persistence.EntityManager;
*/
public class JpaRealmProviderFactory implements RealmProviderFactory {
+ protected RealmListenerHelper listeners = new RealmListenerHelper();
+
@Override
public void init(Config.Scope config) {
}
@@ -26,7 +29,7 @@ public class JpaRealmProviderFactory implements RealmProviderFactory {
@Override
public RealmProvider create(KeycloakSession session) {
EntityManager em = session.getProvider(JpaConnectionProvider.class).getEntityManager();
- return new JpaRealmProvider(session, em);
+ return new JpaRealmProvider(session, em, listeners);
}
@Override
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
index f294bbd..7578fd0 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
@@ -1262,12 +1262,17 @@ public class RealmAdapter implements RealmModel {
for (ProtocolMapperEntity entity : realm.getProtocolClaimMappings()) {
ProtocolMapperModel mapping = new ProtocolMapperModel();
mapping.setId(entity.getId());
+ mapping.setName(entity.getName());
mapping.setProtocol(entity.getProtocol());
- mapping.setProtocolClaim(entity.getProtocolClaim());
mapping.setAppliedByDefault(entity.isAppliedByDefault());
- mapping.setSource(ProtocolMapperModel.Source.valueOf(entity.getSource()));
- mapping.setSourceAttribute(entity.getSourceAttribute());
mapping.setProtocolMapper(entity.getProtocolMapper());
+ mapping.setConsentRequired(entity.isConsentRequired());
+ mapping.setConsentText(entity.getConsentText());
+ Map<String, String> config = new HashMap<String, String>();
+ if (entity.getConfig() != null) {
+ config.putAll(entity.getConfig());
+ }
+ mapping.setConfig(config);
mappings.add(mapping);
}
return mappings;
@@ -1278,26 +1283,29 @@ public class RealmAdapter implements RealmModel {
String id = model.getId() == null ? KeycloakModelUtils.generateId() : model.getId();
ProtocolMapperEntity entity = new ProtocolMapperEntity();
entity.setId(id);
- entity.setSourceAttribute(model.getSourceAttribute());
+ entity.setName(model.getName());
entity.setProtocol(model.getProtocol());
- entity.setProtocolClaim(model.getProtocolClaim());
- entity.setSource(model.getSource().name());
entity.setProtocolMapper(model.getProtocolMapper());
entity.setAppliedByDefault(model.isAppliedByDefault());
entity.setRealm(realm);
+ entity.setConfig(model.getConfig());
+ entity.setConsentRequired(model.isConsentRequired());
+ entity.setConsentText(model.getConsentText());
+
em.persist(entity);
ProtocolMapperModel mapping = new ProtocolMapperModel();
mapping.setId(entity.getId());
+ mapping.setName(model.getName());
mapping.setProtocol(entity.getProtocol());
mapping.setProtocolMapper(entity.getProtocolMapper());
- mapping.setProtocolClaim(entity.getProtocolClaim());
mapping.setAppliedByDefault(entity.isAppliedByDefault());
- mapping.setSource(ProtocolMapperModel.Source.valueOf(entity.getSource()));
- mapping.setSourceAttribute(entity.getSourceAttribute());
+ mapping.setConfig(model.getConfig());
+ mapping.setConsentRequired(entity.isConsentRequired());
+ mapping.setConsentText(entity.getConsentText());
return mapping;
}
- protected ProtocolMapperEntity getProtocolClaimMapping(String id) {
+ protected ProtocolMapperEntity getProtocolMapper(String id) {
for (ProtocolMapperEntity entity : realm.getProtocolClaimMappings()) {
if (entity.getId().equals(id)) {
return entity;
@@ -1309,7 +1317,7 @@ public class RealmAdapter implements RealmModel {
@Override
public void removeProtocolMapper(ProtocolMapperModel mapping) {
- ProtocolMapperEntity toDelete = getProtocolClaimMapping(mapping.getId());
+ ProtocolMapperEntity toDelete = getProtocolMapper(mapping.getId());
if (toDelete != null) {
realm.getProtocolClaimMappings().remove(toDelete);
em.remove(toDelete);
@@ -1319,27 +1327,35 @@ public class RealmAdapter implements RealmModel {
@Override
public void updateProtocolMapper(ProtocolMapperModel mapping) {
- ProtocolMapperEntity entity = getProtocolClaimMapping(mapping.getId());
- entity.setProtocol(mapping.getProtocol());
- entity.setProtocolClaim(mapping.getProtocolClaim());
+ ProtocolMapperEntity entity = getProtocolMapper(mapping.getId());
+ entity.setProtocolMapper(mapping.getProtocolMapper());
entity.setAppliedByDefault(mapping.isAppliedByDefault());
- entity.setSource(mapping.getSource().name());
- entity.setSourceAttribute(mapping.getSourceAttribute());
+ entity.setConsentRequired(mapping.isConsentRequired());
+ entity.setConsentText(mapping.getConsentText());
+ if (entity.getConfig() == null) {
+ entity.setConfig(mapping.getConfig());
+ } else {
+ entity.getConfig().clear();
+ entity.getConfig().putAll(mapping.getConfig());
+ }
em.flush();
}
@Override
public ProtocolMapperModel getProtocolMapperById(String id) {
- ProtocolMapperEntity entity = getProtocolClaimMapping(id);
+ ProtocolMapperEntity entity = getProtocolMapper(id);
if (entity == null) return null;
ProtocolMapperModel mapping = new ProtocolMapperModel();
mapping.setId(entity.getId());
+ mapping.setName(entity.getName());
mapping.setProtocol(entity.getProtocol());
- mapping.setProtocolClaim(entity.getProtocolClaim());
mapping.setAppliedByDefault(entity.isAppliedByDefault());
- mapping.setSource(ProtocolMapperModel.Source.valueOf(entity.getSource()));
- mapping.setSourceAttribute(entity.getSourceAttribute());
+ mapping.setConsentRequired(entity.isConsentRequired());
+ mapping.setConsentText(entity.getConsentText());
+ Map<String, String> config = new HashMap<String, String>();
+ if (entity.getConfig() != null) config.putAll(entity.getConfig());
+ mapping.setConfig(config);
return mapping;
}
}
\ No newline at end of file
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoRealmProvider.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoRealmProvider.java
index 691bce4..3d6b735 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoRealmProvider.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoRealmProvider.java
@@ -8,6 +8,7 @@ import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
import org.keycloak.models.ApplicationModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.OAuthClientModel;
+import org.keycloak.models.RealmListenerHelper;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RealmProvider;
import org.keycloak.models.RoleModel;
@@ -27,10 +28,12 @@ public class MongoRealmProvider implements RealmProvider {
private final MongoStoreInvocationContext invocationContext;
private final KeycloakSession session;
+ protected RealmListenerHelper listeners;
- public MongoRealmProvider(KeycloakSession session, MongoStoreInvocationContext invocationContext) {
+ public MongoRealmProvider(KeycloakSession session, MongoStoreInvocationContext invocationContext, RealmListenerHelper listeners) {
this.session = session;
this.invocationContext = invocationContext;
+ this.listeners = listeners;
}
@Override
@@ -39,6 +42,18 @@ public class MongoRealmProvider implements RealmProvider {
}
@Override
+ public void registerListener(RealmCreationListener listener) {
+ listeners.registerListener(listener);
+ }
+
+ @Override
+ public void unregisterListener(RealmCreationListener listener) {
+ listeners.unregisterListener(listener);
+
+ }
+
+
+ @Override
public RealmModel createRealm(String name) {
return createRealm(KeycloakModelUtils.generateId(), name);
}
@@ -51,7 +66,9 @@ public class MongoRealmProvider implements RealmProvider {
getMongoStore().insertEntity(newRealm, invocationContext);
- return new RealmAdapter(session, newRealm, invocationContext);
+ RealmModel model = new RealmAdapter(session, newRealm, invocationContext);
+ listeners.executeCreationListeners(model);
+ return model;
}
@Override
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoRealmProviderFactory.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoRealmProviderFactory.java
index 9606753..c8f2f11 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoRealmProviderFactory.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoRealmProviderFactory.java
@@ -4,6 +4,7 @@ import org.jboss.logging.Logger;
import org.keycloak.Config;
import org.keycloak.connections.mongo.MongoConnectionProvider;
import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmListenerHelper;
import org.keycloak.models.RealmProvider;
import org.keycloak.models.RealmProviderFactory;
@@ -15,6 +16,8 @@ import org.keycloak.models.RealmProviderFactory;
public class MongoRealmProviderFactory implements RealmProviderFactory {
protected static final Logger logger = Logger.getLogger(MongoRealmProviderFactory.class);
+ protected RealmListenerHelper listeners = new RealmListenerHelper();
+
@Override
public String getId() {
return "mongo";
@@ -27,7 +30,7 @@ public class MongoRealmProviderFactory implements RealmProviderFactory {
@Override
public RealmProvider create(KeycloakSession session) {
MongoConnectionProvider connection = session.getProvider(MongoConnectionProvider.class);
- return new MongoRealmProvider(session, connection.getInvocationContext());
+ return new MongoRealmProvider(session, connection.getInvocationContext(), listeners);
}
@Override
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java
index 0dfac8b..9b20f2a 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java
@@ -789,14 +789,19 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
@Override
public Set<ProtocolMapperModel> getProtocolMappers() {
Set<ProtocolMapperModel> result = new HashSet<ProtocolMapperModel>();
- for (ProtocolMapperEntity entity : realm.getClaimMappings()) {
+ for (ProtocolMapperEntity entity : realm.getProtocolMappers()) {
ProtocolMapperModel mapping = new ProtocolMapperModel();
mapping.setId(entity.getId());
- mapping.setProtocolClaim(entity.getProtocolClaim());
+ mapping.setName(entity.getName());
mapping.setProtocol(entity.getProtocol());
- mapping.setSource(entity.getSource());
- mapping.setSourceAttribute(entity.getSourceAttribute());
mapping.setAppliedByDefault(entity.isAppliedByDefault());
+ mapping.setConsentRequired(entity.isConsentRequired());
+ mapping.setConsentText(entity.getConsentText());
+ Map<String, String> config = new HashMap<String, String>();
+ if (entity.getConfig() != null) {
+ config.putAll(entity.getConfig());
+ }
+ mapping.setConfig(config);
}
return result;
}
@@ -806,30 +811,31 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
ProtocolMapperEntity entity = new ProtocolMapperEntity();
if (model.getId() != null) entity.setId(model.getId());
else entity.setId(KeycloakModelUtils.generateId());
- entity.setSourceAttribute(model.getSourceAttribute());
entity.setProtocol(model.getProtocol());
- entity.setProtocolClaim(model.getProtocolClaim());
- entity.setSource(model.getSource());
+ entity.setName(model.getName());
entity.setAppliedByDefault(model.isAppliedByDefault());
entity.setProtocolMapper(model.getProtocolMapper());
- realm.getClaimMappings().add(entity);
+ entity.setConfig(model.getConfig());
+ entity.setConsentRequired(model.isConsentRequired());
+ entity.setConsentText(model.getConsentText());
+ realm.getProtocolMappers().add(entity);
updateRealm();
ProtocolMapperModel mapping = new ProtocolMapperModel();
mapping.setId(entity.getId());
- mapping.setProtocol(entity.getProtocol());
- mapping.setProtocolClaim(entity.getProtocolClaim());
- mapping.setAppliedByDefault(entity.isAppliedByDefault());
- mapping.setSource(entity.getSource());
- mapping.setSourceAttribute(entity.getSourceAttribute());
- mapping.setProtocolMapper(entity.getProtocolMapper());
+ mapping.setProtocol(model.getProtocol());
+ mapping.setAppliedByDefault(model.isAppliedByDefault());
+ mapping.setProtocolMapper(model.getProtocolMapper());
+ mapping.setConfig(model.getConfig());
+ mapping.setConsentText(model.getConsentText());
+ mapping.setConsentRequired(model.isConsentRequired());
return mapping;
}
@Override
public void removeProtocolMapper(ProtocolMapperModel mapping) {
- for (ProtocolMapperEntity entity : realm.getClaimMappings()) {
+ for (ProtocolMapperEntity entity : realm.getProtocolMappers()) {
if (entity.getId().equals(mapping.getId())) {
- realm.getClaimMappings().remove(entity);
+ realm.getProtocolMappers().remove(entity);
updateRealm();
break;
}
@@ -837,8 +843,8 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
}
- protected ProtocolMapperEntity getProtocolClaimMapping(String id) {
- for (ProtocolMapperEntity entity : realm.getClaimMappings()) {
+ protected ProtocolMapperEntity getProtocolMapper(String id) {
+ for (ProtocolMapperEntity entity : realm.getProtocolMappers()) {
if (entity.getId().equals(id)) {
return entity;
}
@@ -850,29 +856,36 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
@Override
public void updateProtocolMapper(ProtocolMapperModel mapping) {
- ProtocolMapperEntity entity = getProtocolClaimMapping(mapping.getId());
- entity.setProtocol(mapping.getProtocol());
- entity.setProtocolClaim(mapping.getProtocolClaim());
+ ProtocolMapperEntity entity = getProtocolMapper(mapping.getId());
entity.setAppliedByDefault(mapping.isAppliedByDefault());
- entity.setSource(mapping.getSource());
- entity.setSourceAttribute(mapping.getSourceAttribute());
entity.setProtocolMapper(mapping.getProtocolMapper());
+ entity.setConsentRequired(mapping.isConsentRequired());
+ entity.setConsentText(mapping.getConsentText());
+ if (entity.getConfig() != null) {
+ entity.getConfig().clear();
+ entity.getConfig().putAll(mapping.getConfig());
+ } else {
+ entity.setConfig(mapping.getConfig());
+ }
updateRealm();
}
@Override
public ProtocolMapperModel getProtocolMapperById(String id) {
- ProtocolMapperEntity entity = getProtocolClaimMapping(id);
+ ProtocolMapperEntity entity = getProtocolMapper(id);
if (entity == null) return null;
ProtocolMapperModel mapping = new ProtocolMapperModel();
mapping.setId(entity.getId());
+ mapping.setName(entity.getName());
mapping.setProtocol(entity.getProtocol());
- mapping.setProtocolClaim(entity.getProtocolClaim());
mapping.setAppliedByDefault(entity.isAppliedByDefault());
- mapping.setSource(entity.getSource());
- mapping.setSourceAttribute(entity.getSourceAttribute());
mapping.setProtocolMapper(entity.getProtocolMapper());
+ mapping.setConsentRequired(entity.isConsentRequired());
+ mapping.setConsentText(entity.getConsentText());
+ Map<String, String> config = new HashMap<String, String>();
+ if (entity.getConfig() != null) config.putAll(config);
+ mapping.setConfig(config);
return mapping;
}
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCClientSessionNoteMapper.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCClientSessionNoteMapper.java
new file mode 100755
index 0000000..3e38ed2
--- /dev/null
+++ b/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCClientSessionNoteMapper.java
@@ -0,0 +1,60 @@
+package org.keycloak.protocol.oidc.mappers;
+
+import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.UserSessionModel;
+import org.keycloak.representations.AccessToken;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Mappings UserSessionModel.note to an ID Token claim. Token claim name can be a full qualified nested object name,
+ * i.e. "address.country". This will create a nested
+ * json object within the toke claim.
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class OIDCClientSessionNoteMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper {
+ private static final List<ConfigProperty> configProperties = new ArrayList<ConfigProperty>();
+ public static final String CLIENT_SESSION_NOTE = "ClientSession Note";
+
+ static {
+ ConfigProperty property;
+ property = new ConfigProperty();
+ property.setName(CLIENT_SESSION_NOTE);
+ property.setLabel(CLIENT_SESSION_NOTE);
+ property.setHelpText("Name of the note to map in the UserSessionModel");
+ configProperties.add(property);
+ property.setName(OIDCUserAttributeMapper.TOKEN_CLAIM_NAME);
+ property.setLabel(OIDCUserAttributeMapper.TOKEN_CLAIM_NAME);
+ property.setHelpText("Name of the claim to insert into the token. This can be a fully qualified name like 'address.street'. In this case, a nested json object will be created.");
+ configProperties.add(property);
+
+ }
+
+ public List<ConfigProperty> getConfigProperties() {
+ return configProperties;
+ }
+ @Override
+ public String getId() {
+ return "oidc-client-session-note-mapper";
+ }
+
+ @Override
+ public String getDisplayType() {
+ return "ClientSession Note Mapper";
+ }
+
+ @Override
+ public AccessToken transformToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
+ UserSessionModel userSession, ClientSessionModel clientSession) {
+ String note = mappingModel.getConfig().get(CLIENT_SESSION_NOTE);
+ String noteValue = clientSession.getNote(note);
+ OIDCUserAttributeMapper.mapClaim(token, mappingModel, noteValue);
+ return token;
+ }
+
+}
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCUserModelMapper.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCUserModelMapper.java
new file mode 100755
index 0000000..4af3178
--- /dev/null
+++ b/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCUserModelMapper.java
@@ -0,0 +1,79 @@
+package org.keycloak.protocol.oidc.mappers;
+
+import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.UserSessionModel;
+import org.keycloak.representations.AccessToken;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Mappings UserModel property (the property name of a getter method) to an ID Token claim. Token claim name can be a full qualified nested object name,
+ * i.e. "address.country". This will create a nested
+ * json object within the toke claim.
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class OIDCUserModelMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper {
+ private static final List<ConfigProperty> configProperties = new ArrayList<ConfigProperty>();
+ public static final String USER_MODEL_PROPERTY = "UserModel Property";
+
+ static {
+ ConfigProperty property;
+ property = new ConfigProperty();
+ property.setName(USER_MODEL_PROPERTY);
+ property.setLabel(USER_MODEL_PROPERTY);
+ property.setHelpText("Name of the property method in the UserModel interface. For example, a value of 'email' would reference the UserModel.getEmail() method.");
+ configProperties.add(property);
+ property.setName(OIDCUserAttributeMapper.TOKEN_CLAIM_NAME);
+ property.setLabel(OIDCUserAttributeMapper.TOKEN_CLAIM_NAME);
+ property.setHelpText("Name of the claim to insert into the token. This can be a fully qualified name like 'address.street'. In this case, a nested json object will be created.");
+ configProperties.add(property);
+
+ }
+
+
+ public List<ConfigProperty> getConfigProperties() {
+ return configProperties;
+ }
+ @Override
+ public String getId() {
+ return "oidc-usermodel-property-mapper";
+ }
+
+ @Override
+ public String getDisplayType() {
+ return "UserModel Property Mapper";
+ }
+
+ @Override
+ public AccessToken transformToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
+ UserSessionModel userSession, ClientSessionModel clientSession) {
+ UserModel user = userSession.getUser();
+ String propertyName = mappingModel.getConfig().get(USER_MODEL_PROPERTY);
+ String propertyValue = getUserModelValue(user,propertyName);
+ OIDCUserAttributeMapper.mapClaim(token, mappingModel, propertyValue);
+
+ return token;
+ }
+
+ protected String getUserModelValue(UserModel user, String propertyName) {
+
+ String methodName = "get" + Character.toUpperCase(propertyName.charAt(0)) + propertyName.substring(1);
+ try {
+ Method method = UserModel.class.getMethod(methodName);
+ Object val = method.invoke(user);
+ if (val != null) return val.toString();
+ } catch (Exception ignore) {
+
+ }
+ return null;
+ }
+}
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCUserSessionNoteMapper.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCUserSessionNoteMapper.java
new file mode 100755
index 0000000..0069d5a
--- /dev/null
+++ b/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCUserSessionNoteMapper.java
@@ -0,0 +1,61 @@
+package org.keycloak.protocol.oidc.mappers;
+
+import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.UserSessionModel;
+import org.keycloak.representations.AccessToken;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Mappings UserSessionModel.note to an ID Token claim. Token claim name can be a full qualified nested object name,
+ * i.e. "address.country". This will create a nested
+ * json object within the toke claim.
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class OIDCUserSessionNoteMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper {
+ private static final List<ConfigProperty> configProperties = new ArrayList<ConfigProperty>();
+ public static final String USER_SESSION_NOTE = "UserSession Note";
+
+ static {
+ ConfigProperty property;
+ property = new ConfigProperty();
+ property.setName(USER_SESSION_NOTE);
+ property.setLabel("UserSession Note");
+ property.setHelpText("Name of the note to map in the UserSessionModel");
+ configProperties.add(property);
+ property.setName(OIDCUserAttributeMapper.TOKEN_CLAIM_NAME);
+ property.setLabel(OIDCUserAttributeMapper.TOKEN_CLAIM_NAME);
+ property.setHelpText("Name of the claim to insert into the token. This can be a fully qualified name like 'address.street'. In this case, a nested json object will be created.");
+ configProperties.add(property);
+
+ }
+
+ public List<ConfigProperty> getConfigProperties() {
+ return configProperties;
+ }
+
+ @Override
+ public String getId() {
+ return "oidc-user-session-note-mapper";
+ }
+
+ @Override
+ public String getDisplayType() {
+ return "UserSession Note Mapper";
+ }
+
+ @Override
+ public AccessToken transformToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
+ UserSessionModel userSession, ClientSessionModel clientSession) {
+ String note = mappingModel.getConfig().get(USER_SESSION_NOTE);
+ String noteValue = userSession.getNote(note);
+ OIDCUserAttributeMapper.mapClaim(token, mappingModel, noteValue);
+ return token;
+ }
+
+}
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolFactory.java b/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolFactory.java
index 3c4a800..b0e3605 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolFactory.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolFactory.java
@@ -20,6 +20,7 @@ public class OIDCLoginProtocolFactory implements LoginProtocolFactory {
@Override
public void init(Config.Scope config) {
+ System.out.println("here");
}
diff --git a/services/src/main/java/org/keycloak/protocol/ProtocolMapper.java b/services/src/main/java/org/keycloak/protocol/ProtocolMapper.java
index 8697d72..c202847 100755
--- a/services/src/main/java/org/keycloak/protocol/ProtocolMapper.java
+++ b/services/src/main/java/org/keycloak/protocol/ProtocolMapper.java
@@ -3,6 +3,8 @@ package org.keycloak.protocol;
import org.keycloak.provider.Provider;
import org.keycloak.provider.ProviderFactory;
+import java.util.List;
+
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
@@ -10,4 +12,36 @@ import org.keycloak.provider.ProviderFactory;
public interface ProtocolMapper extends Provider, ProviderFactory<ProtocolMapper> {
String getProtocol();
String getDisplayType();
+
+ public static class ConfigProperty {
+ protected String name;
+ protected String label;
+ protected String helpText;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getLabel() {
+ return label;
+ }
+
+ public void setLabel(String label) {
+ this.label = label;
+ }
+
+ public String getHelpText() {
+ return helpText;
+ }
+
+ public void setHelpText(String helpText) {
+ this.helpText = helpText;
+ }
+ }
+
+ List<ConfigProperty> getConfigProperties();
}
diff --git a/services/src/main/resources/META-INF/services/org.keycloak.protocol.ProtocolMapper b/services/src/main/resources/META-INF/services/org.keycloak.protocol.ProtocolMapper
index 0310583..0f9da65 100755
--- a/services/src/main/resources/META-INF/services/org.keycloak.protocol.ProtocolMapper
+++ b/services/src/main/resources/META-INF/services/org.keycloak.protocol.ProtocolMapper
@@ -1 +1 @@
-org.keycloak.protocol.oidc.OIDCAttributeToTokenMapper
\ No newline at end of file
+org.keycloak.protocol.oidc.mappers.OIDCUserAttributeMapper
\ No newline at end of file