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 f48615b18c4..943420387d6 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 @@ -63,6 +63,14 @@ + + + + + + + + @@ -78,6 +86,8 @@ + + diff --git a/core/src/main/java/org/keycloak/representations/idm/ApplicationRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/ApplicationRepresentation.java index 33698936e18..0e42a40ba74 100755 --- a/core/src/main/java/org/keycloak/representations/idm/ApplicationRepresentation.java +++ b/core/src/main/java/org/keycloak/representations/idm/ApplicationRepresentation.java @@ -2,6 +2,7 @@ package org.keycloak.representations.idm; import java.util.List; import java.util.Map; +import java.util.Set; /** * @author Bill Burke @@ -29,6 +30,7 @@ public class ApplicationRepresentation { protected Integer nodeReRegistrationTimeout; protected Map registeredNodes; protected List allowedIdentityProviders; + protected Set protocolClaimMappings; public String getId() { return id; @@ -197,4 +199,12 @@ public class ApplicationRepresentation { public void setAllowedIdentityProviders(List allowedIdentityProviders) { this.allowedIdentityProviders = allowedIdentityProviders; } + + public Set getProtocolClaimMappings() { + return protocolClaimMappings; + } + + public void setProtocolClaimMappings(Set protocolClaimMappings) { + this.protocolClaimMappings = protocolClaimMappings; + } } diff --git a/core/src/main/java/org/keycloak/representations/idm/OAuthClientRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/OAuthClientRepresentation.java index 12ce2f45879..dcb6ba805e6 100755 --- a/core/src/main/java/org/keycloak/representations/idm/OAuthClientRepresentation.java +++ b/core/src/main/java/org/keycloak/representations/idm/OAuthClientRepresentation.java @@ -2,6 +2,7 @@ package org.keycloak.representations.idm; import java.util.List; import java.util.Map; +import java.util.Set; /** * @author Bill Burke @@ -23,6 +24,7 @@ public class OAuthClientRepresentation { protected Boolean fullScopeAllowed; protected Boolean frontchannelLogout; protected List allowedIdentityProviders; + protected Set protocolClaimMappings; public String getId() { @@ -144,4 +146,12 @@ public class OAuthClientRepresentation { public void setAllowedIdentityProviders(List allowedIdentityProviders) { this.allowedIdentityProviders = allowedIdentityProviders; } + + public Set getProtocolClaimMappings() { + return protocolClaimMappings; + } + + public void setProtocolClaimMappings(Set protocolClaimMappings) { + this.protocolClaimMappings = protocolClaimMappings; + } } diff --git a/model/api/src/main/java/org/keycloak/models/ClientModel.java b/model/api/src/main/java/org/keycloak/models/ClientModel.java index 5fa685f44bc..3e3c53d5060 100755 --- a/model/api/src/main/java/org/keycloak/models/ClientModel.java +++ b/model/api/src/main/java/org/keycloak/models/ClientModel.java @@ -104,10 +104,7 @@ public interface ClientModel { boolean hasIdentityProvider(String providerId); - /* - Set getClaimMappings(); - ProtocolClaimMapping getClaimMapping(String protocolClaim); - ProtocolClaimMapping addClaimMapping(String assertion, String protocol, ClaimTypeModel claimType); - void removeClaimMapping(ProtocolClaimMapping mapping); - */ + Set getProtocolClaimMappings(); + void addProtocolClaimMappings(Set mappingIds); + void removeProtocolClaimMappings(Set mappingIds); } diff --git a/model/api/src/main/java/org/keycloak/models/entities/ClientEntity.java b/model/api/src/main/java/org/keycloak/models/entities/ClientEntity.java index f6e428fdfeb..1cfbcfe32da 100755 --- a/model/api/src/main/java/org/keycloak/models/entities/ClientEntity.java +++ b/model/api/src/main/java/org/keycloak/models/entities/ClientEntity.java @@ -2,8 +2,10 @@ package org.keycloak.models.entities; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; /** * @author Marek Posolda @@ -28,6 +30,7 @@ public class ClientEntity extends AbstractIdentifiableEntity { private List redirectUris = new ArrayList(); private List scopeIds = new ArrayList(); private List allowedIdentityProviders = new ArrayList(); + private Set protocolClaimMappings = new HashSet(); public String getName() { return name; @@ -148,4 +151,12 @@ public class ClientEntity extends AbstractIdentifiableEntity { public void setAllowedIdentityProviders(List allowedIdentityProviders) { this.allowedIdentityProviders = allowedIdentityProviders; } + + public Set getProtocolClaimMappings() { + return protocolClaimMappings; + } + + public void setProtocolClaimMappings(Set protocolClaimMappings) { + this.protocolClaimMappings = protocolClaimMappings; + } } 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 c2c91eba3a5..6bff99eea83 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 @@ -265,6 +265,12 @@ public class ModelToRepresentation { rep.setAllowedIdentityProviders(applicationModel.getAllowedIdentityProviders()); } + if (!applicationModel.getProtocolClaimMappings().isEmpty()) { + Set mappings = new HashSet(); + for (ProtocolClaimMappingModel model : applicationModel.getProtocolClaimMappings()) mappings.add(model.getId()); + rep.setProtocolClaimMappings(mappings); + } + return rep; } @@ -294,6 +300,11 @@ public class ModelToRepresentation { rep.setAllowedIdentityProviders(model.getAllowedIdentityProviders()); } + if (!model.getProtocolClaimMappings().isEmpty()) { + Set mappings = new HashSet(); + for (ProtocolClaimMappingModel mappingMoel : model.getProtocolClaimMappings()) mappings.add(mappingMoel.getId()); + rep.setProtocolClaimMappings(mappings); + } 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 c3aad659d9b..a4b87ba0fcf 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 @@ -460,6 +460,10 @@ public class RepresentationToModel { applicationModel.setAllowedClaimsMask(ClaimMask.ALL); } + if (resourceRep.getProtocolClaimMappings() != null) { + applicationModel.addProtocolClaimMappings(resourceRep.getProtocolClaimMappings()); + } + return applicationModel; } @@ -632,6 +636,11 @@ public class RepresentationToModel { if (rep.getAllowedIdentityProviders() != null) { model.updateAllowedIdentityProviders(rep.getAllowedIdentityProviders()); } + + if (rep.getProtocolClaimMappings() != null) { + model.addProtocolClaimMappings(rep.getProtocolClaimMappings()); + } + } // Scope mappings diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/ClientAdapter.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/ClientAdapter.java index 11696c55072..9055fa72d14 100755 --- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/ClientAdapter.java +++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/ClientAdapter.java @@ -1,6 +1,7 @@ package org.keycloak.models.cache; import org.keycloak.models.ClientModel; +import org.keycloak.models.ProtocolClaimMappingModel; import org.keycloak.models.RealmModel; import org.keycloak.models.RoleContainerModel; import org.keycloak.models.RoleModel; @@ -278,4 +279,23 @@ public abstract class ClientAdapter implements ClientModel { if (updatedClient != null) return updatedClient.hasIdentityProvider(providerId); return cachedClient.hasIdentityProvider(providerId); } + + @Override + public Set getProtocolClaimMappings() { + if (updatedClient != null) return updatedClient.getProtocolClaimMappings(); + return cachedClient.getProtocolClaimMappings(); } + + @Override + public void addProtocolClaimMappings(Set mappingIds) { + getDelegateForUpdate(); + updatedClient.addProtocolClaimMappings(mappingIds); + + } + + @Override + public void removeProtocolClaimMappings(Set mappingIds) { + getDelegateForUpdate(); + updatedClient.removeProtocolClaimMappings(mappingIds); + + } } diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedClient.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedClient.java index ac7341d4a8a..f6c70960e88 100755 --- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedClient.java +++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedClient.java @@ -1,6 +1,7 @@ package org.keycloak.models.cache.entities; import org.keycloak.models.ClientModel; +import org.keycloak.models.ProtocolClaimMappingModel; import org.keycloak.models.RealmModel; import org.keycloak.models.RealmProvider; import org.keycloak.models.RoleModel; @@ -35,6 +36,7 @@ public class CachedClient { protected Set scope = new HashSet(); protected Set webOrigins = new HashSet(); private List allowedIdentityProviders = new ArrayList(); + private Set protocolClaimMappings = new HashSet(); public CachedClient(RealmCache cache, RealmProvider delegate, RealmModel realm, ClientModel model) { id = model.getId(); @@ -56,6 +58,7 @@ public class CachedClient { scope.add(role.getId()); } this.allowedIdentityProviders = model.getAllowedIdentityProviders(); + protocolClaimMappings.addAll(model.getProtocolClaimMappings()); } public String getId() { @@ -122,10 +125,6 @@ public class CachedClient { return frontchannelLogout; } - public void setFrontchannelLogout(boolean frontchannelLogout) { - this.frontchannelLogout = frontchannelLogout; - } - public List getAllowedIdentityProviders() { return this.allowedIdentityProviders; } @@ -137,4 +136,8 @@ public class CachedClient { return this.allowedIdentityProviders.contains(providerId); } + + public Set getProtocolClaimMappings() { + return protocolClaimMappings; + } } 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 e8fb9436fab..8410cfc6d47 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/ClientAdapter.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/ClientAdapter.java @@ -1,11 +1,13 @@ package org.keycloak.models.jpa; import org.keycloak.models.ClientModel; +import org.keycloak.models.ProtocolClaimMappingModel; import org.keycloak.models.RealmModel; import org.keycloak.models.RoleContainerModel; import org.keycloak.models.RoleModel; import org.keycloak.models.jpa.entities.ClientEntity; import org.keycloak.models.jpa.entities.IdentityProviderEntity; +import org.keycloak.models.jpa.entities.ProtocolClaimMappingEntity; import org.keycloak.models.jpa.entities.RoleEntity; import org.keycloak.models.jpa.entities.ScopeMappingEntity; @@ -15,6 +17,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; @@ -352,4 +355,53 @@ public abstract class ClientAdapter implements ClientModel { } return false; } + + @Override + public Set getProtocolClaimMappings() { + Set mappings = new HashSet(); + for (ProtocolClaimMappingEntity entity : this.entity.getProtocolClaimMappings()) { + ProtocolClaimMappingModel mapping = new ProtocolClaimMappingModel(); + mapping.setId(entity.getId()); + mapping.setProtocol(entity.getProtocol()); + mapping.setProtocolClaim(entity.getProtocolClaim()); + mapping.setAppliedByDefault(entity.isAppliedByDefault()); + mapping.setSource(ProtocolClaimMappingModel.Source.valueOf(entity.getSource())); + mapping.setSourceAttribute(entity.getSourceAttribute()); + mappings.add(mapping); + } + return mappings; + } + + @Override + public void addProtocolClaimMappings(Set mappings) { + Collection entities = entity.getProtocolClaimMappings(); + Set already = new HashSet(); + for (ProtocolClaimMappingEntity rel : entities) { + already.add(rel.getId()); + } + for (String providerId : mappings) { + if (!already.contains(providerId)) { + ProtocolClaimMappingEntity mapping = em.find(ProtocolClaimMappingEntity.class, providerId); + if (mapping != null) { + entities.add(mapping); + } + } + } + em.flush(); + } + + @Override + public void removeProtocolClaimMappings(Set mappings) { + Collection entities = entity.getProtocolClaimMappings(); + List remove = new LinkedList(); + for (ProtocolClaimMappingEntity rel : entities) { + if (mappings.contains(rel.getId())) remove.add(rel); + } + for (ProtocolClaimMappingEntity entity : remove) { + entities.remove(entity); + } + em.flush(); + } + + } 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 c62a9c92b2d..755fb6bff93 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 @@ -93,7 +93,7 @@ public class JpaRealmProvider implements RealmProvider { adapter.removeOAuthClient(oauth.getId()); } - em.remove(realm); + em.remove(realm); return true; } diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientEntity.java index ac436562cef..36e588880c3 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientEntity.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientEntity.java @@ -1,5 +1,6 @@ package org.keycloak.models.jpa.entities; +import javax.persistence.CascadeType; import javax.persistence.CollectionTable; import javax.persistence.Column; import javax.persistence.ElementCollection; @@ -76,6 +77,10 @@ public abstract class ClientEntity { @JoinTable(name="CLIENT_ALLOWED_IDENTITY_PROVIDER", joinColumns = { @JoinColumn(name="CLIENT_ID")}, inverseJoinColumns = { @JoinColumn(name="INTERNAL_ID")}) Collection allowedIdentityProviders = new ArrayList(); + @OneToMany(cascade ={CascadeType.REMOVE}) + @JoinTable(name="CLIENT_PROTOCOL_CLAIM_MAPPING", joinColumns = { @JoinColumn(name="CLIENT_ID")}, inverseJoinColumns = { @JoinColumn(name="MAPPING_ID")}) + Collection protocolClaimMappings = new ArrayList(); + public RealmEntity getRealm() { return realm; } @@ -195,4 +200,12 @@ public abstract class ClientEntity { public void setAllowedIdentityProviders(Collection allowedIdentityProviders) { this.allowedIdentityProviders = allowedIdentityProviders; } + + public Collection getProtocolClaimMappings() { + return protocolClaimMappings; + } + + public void setProtocolClaimMappings(Collection protocolClaimMappings) { + this.protocolClaimMappings = protocolClaimMappings; + } } diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/IdentityProviderEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/IdentityProviderEntity.java index b1a9f10d055..cf85fad4d5c 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/IdentityProviderEntity.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/IdentityProviderEntity.java @@ -138,4 +138,6 @@ public class IdentityProviderEntity { public void setConfig(Map config) { this.config = config; } + + } \ No newline at end of file diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ProtocolClaimMappingEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ProtocolClaimMappingEntity.java index 7a429dc8f4e..c3fb6c0e40c 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ProtocolClaimMappingEntity.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ProtocolClaimMappingEntity.java @@ -95,4 +95,21 @@ public class ProtocolClaimMappingEntity { public void setRealm(RealmEntity realm) { this.realm = realm; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + ProtocolClaimMappingEntity that = (ProtocolClaimMappingEntity) o; + + if (!id.equals(that.id)) return false; + + return true; + } + + @Override + public int hashCode() { + return id.hashCode(); + } } diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/ClientAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/ClientAdapter.java index d3f93db902a..11ecd61fd0d 100755 --- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/ClientAdapter.java +++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/ClientAdapter.java @@ -4,6 +4,7 @@ import org.keycloak.connections.mongo.api.MongoIdentifiableEntity; import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext; import org.keycloak.models.ClientModel; import org.keycloak.models.KeycloakSession; +import org.keycloak.models.ProtocolClaimMappingModel; import org.keycloak.models.RealmModel; import org.keycloak.models.RealmProvider; import org.keycloak.models.RoleModel; @@ -291,6 +292,29 @@ public abstract class ClientAdapter extends A return copy; } + @Override + public Set getProtocolClaimMappings() { + Set result = new HashSet(); + for (String id : getMongoEntityAsClient().getProtocolClaimMappings()) { + ProtocolClaimMappingModel model = getRealm().getProtocolClaimMappingById(id); + if (model != null) result.add(model); + } + return result; + } + + @Override + public void addProtocolClaimMappings(Set mappingIds) { + getMongoEntityAsClient().getProtocolClaimMappings().addAll(mappingIds); + updateMongoEntity(); + + } + + @Override + public void removeProtocolClaimMappings(Set mappingIds) { + getMongoEntityAsClient().getProtocolClaimMappings().removeAll(mappingIds); + updateMongoEntity(); + } + @Override public void updateAllowedIdentityProviders(List identityProviders) { List providerIds = new ArrayList();