diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/UserCacheSession.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/UserCacheSession.java index e2fcc83f24..be3d0ad679 100755 --- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/UserCacheSession.java +++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/UserCacheSession.java @@ -54,6 +54,7 @@ import org.keycloak.storage.CacheableStorageProviderModel; import org.keycloak.storage.StorageId; import org.keycloak.storage.UserStorageProvider; import org.keycloak.storage.UserStorageProviderModel; +import org.keycloak.storage.client.ClientStorageProvider; import java.util.Calendar; import java.util.HashMap; @@ -853,7 +854,7 @@ public class UserCacheSession implements UserCache { @Override public void preRemove(RealmModel realm, ComponentModel component) { - if (!component.getProviderType().equals(UserStorageProvider.class.getName())) return; + if (!component.getProviderType().equals(UserStorageProvider.class.getName()) && !component.getProviderType().equals(ClientStorageProvider.class.getName())) return; addRealmInvalidation(realm.getId()); // easier to just invalidate whole realm getDelegate().preRemove(realm, component); diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProvider.java b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProvider.java index 08f316425d..8eb8102672 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProvider.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProvider.java @@ -45,7 +45,9 @@ import org.keycloak.models.jpa.entities.UserConsentRoleEntity; import org.keycloak.models.jpa.entities.UserEntity; import org.keycloak.models.utils.DefaultRoles; import org.keycloak.models.utils.KeycloakModelUtils; +import org.keycloak.storage.StorageId; import org.keycloak.storage.UserStorageProvider; +import org.keycloak.storage.client.ClientStorageProvider; import javax.persistence.EntityManager; import javax.persistence.TypedQuery; @@ -194,7 +196,14 @@ public class JpaUserProvider implements UserProvider, UserCredentialStore { consentEntity = new UserConsentEntity(); consentEntity.setId(KeycloakModelUtils.generateId()); consentEntity.setUser(em.getReference(UserEntity.class, userId)); - consentEntity.setClientId(clientId); + StorageId clientStorageId = new StorageId(clientId); + if (clientStorageId.isLocal()) { + consentEntity.setClientId(clientId); + } else { + consentEntity.setClientStorageProvider(clientStorageId.getProviderId()); + consentEntity.setExternalClientId(clientStorageId.getExternalId()); + } + consentEntity.setCreatedDate(currentTime); consentEntity.setLastUpdatedDate(currentTime); em.persist(consentEntity); @@ -246,9 +255,16 @@ public class JpaUserProvider implements UserProvider, UserCredentialStore { private UserConsentEntity getGrantedConsentEntity(String userId, String clientId) { - TypedQuery query = em.createNamedQuery("userConsentByUserAndClient", UserConsentEntity.class); + StorageId clientStorageId = new StorageId(clientId); + String queryName = clientStorageId.isLocal() ? "userConsentByUserAndClient" : "userConsentByUserAndExternalClient"; + TypedQuery query = em.createNamedQuery(queryName, UserConsentEntity.class); query.setParameter("userId", userId); - query.setParameter("clientId", clientId); + if (clientStorageId.isLocal()) { + query.setParameter("clientId", clientId); + } else { + query.setParameter("clientStorageProvider", clientStorageId.getProviderId()); + query.setParameter("externalClientId", clientStorageId.getExternalId()); + } List results = query.getResultList(); if (results.size() > 1) { throw new ModelException("More results found for user [" + userId + "] and client [" + clientId + "]"); @@ -257,6 +273,7 @@ public class JpaUserProvider implements UserProvider, UserCredentialStore { } else { return null; } + } private UserConsentModel toConsentModel(RealmModel realm, UserConsentEntity entity) { @@ -264,9 +281,16 @@ public class JpaUserProvider implements UserProvider, UserCredentialStore { return null; } - ClientModel client = realm.getClientById(entity.getClientId()); + StorageId clientStorageId = null; + if ( entity.getClientId() == null) { + clientStorageId = new StorageId(entity.getClientStorageProvider(), entity.getExternalClientId()); + } else { + clientStorageId = new StorageId(entity.getClientId()); + } + + ClientModel client = realm.getClientById(clientStorageId.getId()); if (client == null) { - throw new ModelException("Client with id " + entity.getClientId() + " is not available"); + throw new ModelException("Client with id " + clientStorageId.getId() + " is not available"); } UserConsentModel model = new UserConsentModel(client); model.setCreatedDate(entity.getCreatedDate()); @@ -472,9 +496,32 @@ public class JpaUserProvider implements UserProvider, UserCredentialStore { @Override public void preRemove(RealmModel realm, ClientModel client) { - em.createNamedQuery("deleteUserConsentProtMappersByClient").setParameter("clientId", client.getId()).executeUpdate(); - em.createNamedQuery("deleteUserConsentRolesByClient").setParameter("clientId", client.getId()).executeUpdate(); - em.createNamedQuery("deleteUserConsentsByClient").setParameter("clientId", client.getId()).executeUpdate(); + StorageId clientStorageId = new StorageId(client.getId()); + if (clientStorageId.isLocal()) { + em.createNamedQuery("deleteUserConsentProtMappersByClient") + .setParameter("clientId", client.getId()) + .executeUpdate(); + em.createNamedQuery("deleteUserConsentRolesByClient") + .setParameter("clientId", client.getId()) + .executeUpdate(); + em.createNamedQuery("deleteUserConsentsByClient") + .setParameter("clientId", client.getId()) + .executeUpdate(); + } else { + em.createNamedQuery("deleteUserConsentProtMappersByExternalClient") + .setParameter("clientStorageProvider", clientStorageId.getProviderId()) + .setParameter("externalClientId",clientStorageId.getExternalId()) + .executeUpdate(); + em.createNamedQuery("deleteUserConsentRolesByExternalClient") + .setParameter("clientStorageProvider", clientStorageId.getProviderId()) + .setParameter("externalClientId", clientStorageId.getExternalId()) + .executeUpdate(); + em.createNamedQuery("deleteUserConsentsByExternalClient") + .setParameter("clientStorageProvider", clientStorageId.getProviderId()) + .setParameter("externalClientId", clientStorageId.getExternalId()) + .executeUpdate(); + + } } @Override @@ -806,8 +853,24 @@ public class JpaUserProvider implements UserProvider, UserCredentialStore { @Override public void preRemove(RealmModel realm, ComponentModel component) { - if (!component.getProviderType().equals(UserStorageProvider.class.getName())) return; - removeImportedUsers(realm, component.getId()); + if (component.getProviderType().equals(UserStorageProvider.class.getName())) { + removeImportedUsers(realm, component.getId()); + } + if (component.getProviderType().equals(ClientStorageProvider.class.getName())) { + removeConsentByClientStorageProvider(realm, component.getId()); + } + } + + protected void removeConsentByClientStorageProvider(RealmModel realm, String providerId) { + em.createNamedQuery("deleteUserConsentProtMappersByClientStorageProvider") + .setParameter("clientStorageProvider", providerId) + .executeUpdate(); + em.createNamedQuery("deleteUserConsentRolesByClientStorageProvider") + .setParameter("clientStorageProvider", providerId) + .executeUpdate(); + em.createNamedQuery("deleteUserConsentsByClientStorageProvider") + .setParameter("clientStorageProvider", providerId) + .executeUpdate(); } diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserConsentEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserConsentEntity.java index a29ab6925e..9772810b5e 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserConsentEntity.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserConsentEntity.java @@ -43,11 +43,14 @@ import java.util.Collection; }) @NamedQueries({ @NamedQuery(name="userConsentByUserAndClient", query="select consent from UserConsentEntity consent where consent.user.id = :userId and consent.clientId = :clientId"), + @NamedQuery(name="userConsentByUserAndExternalClient", query="select consent from UserConsentEntity consent where consent.user.id = :userId and consent.clientStorageProvider = :clientStorageProvider and consent.externalClientId = :externalClientId"), @NamedQuery(name="userConsentsByUser", query="select consent from UserConsentEntity consent where consent.user.id = :userId"), @NamedQuery(name="deleteUserConsentsByRealm", query="delete from UserConsentEntity consent where consent.user IN (select user from UserEntity user where user.realmId = :realmId)"), @NamedQuery(name="deleteUserConsentsByRealmAndLink", query="delete from UserConsentEntity consent where consent.user IN (select u from UserEntity u where u.realmId=:realmId and u.federationLink=:link)"), @NamedQuery(name="deleteUserConsentsByUser", query="delete from UserConsentEntity consent where consent.user = :user"), @NamedQuery(name="deleteUserConsentsByClient", query="delete from UserConsentEntity consent where consent.clientId = :clientId"), + @NamedQuery(name="deleteUserConsentsByExternalClient", query="delete from UserConsentEntity consent where consent.clientStorageProvider = :clientStorageProvider and consent.externalClientId = :externalClientId"), + @NamedQuery(name="deleteUserConsentsByClientStorageProvider", query="delete from UserConsentEntity consent where consent.clientStorageProvider = :clientStorageProvider"), }) public class UserConsentEntity { @@ -63,6 +66,12 @@ public class UserConsentEntity { @Column(name="CLIENT_ID") protected String clientId; + @Column(name="CLIENT_STORAGE_PROVIDER") + protected String clientStorageProvider; + + @Column(name="EXTERNAL_CLIENT_ID") + protected String externalClientId; + @OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "userConsent") Collection grantedRoles = new ArrayList(); @@ -91,14 +100,6 @@ public class UserConsentEntity { this.user = user; } - public String getClientId() { - return clientId; - } - - public void setClientId(String clientId) { - this.clientId = clientId; - } - public Collection getGrantedRoles() { return grantedRoles; } @@ -131,6 +132,30 @@ public class UserConsentEntity { this.lastUpdatedDate = lastUpdatedDate; } + public String getClientId() { + return clientId; + } + + public void setClientId(String clientId) { + this.clientId = clientId; + } + + public String getClientStorageProvider() { + return clientStorageProvider; + } + + public void setClientStorageProvider(String clientStorageProvider) { + this.clientStorageProvider = clientStorageProvider; + } + + public String getExternalClientId() { + return externalClientId; + } + + public void setExternalClientId(String externalClientId) { + this.externalClientId = externalClientId; + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserConsentProtocolMapperEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserConsentProtocolMapperEntity.java index 4c0dd5d74a..85df7598ee 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserConsentProtocolMapperEntity.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserConsentProtocolMapperEntity.java @@ -38,7 +38,9 @@ import java.io.Serializable; @NamedQuery(name="deleteUserConsentProtMappersByUser", query="delete from UserConsentProtocolMapperEntity csm where csm.userConsent IN (select consent from UserConsentEntity consent where consent.user = :user)"), @NamedQuery(name="deleteUserConsentProtMappersByRealmAndLink", query="delete from UserConsentProtocolMapperEntity csm where csm.userConsent IN (select consent from UserConsentEntity consent where consent.user IN (select u from UserEntity u where u.realmId=:realmId and u.federationLink=:link))"), @NamedQuery(name="deleteUserConsentProtMappersByProtocolMapper", query="delete from UserConsentProtocolMapperEntity csm where csm.protocolMapperId = :protocolMapperId)"), - @NamedQuery(name="deleteUserConsentProtMappersByClient", query="delete from UserConsentProtocolMapperEntity csm where csm.userConsent IN (select consent from UserConsentEntity consent where consent.clientId = :clientId))"), + @NamedQuery(name="deleteUserConsentProtMappersByClient", query="delete from UserConsentProtocolMapperEntity csm where csm.userConsent IN (select consent from UserConsentEntity consent where consent.clientId = :clientId)"), + @NamedQuery(name="deleteUserConsentProtMappersByExternalClient", query="delete from UserConsentProtocolMapperEntity csm where csm.userConsent IN (select consent from UserConsentEntity consent where consent.clientStorageProvider = :clientStorageProvider and consent.externalClientId = :externalClientId)"), + @NamedQuery(name="deleteUserConsentProtMappersByClientStorageProvider", query="delete from UserConsentProtocolMapperEntity csm where csm.userConsent IN (select consent from UserConsentEntity consent where consent.clientStorageProvider = :clientStorageProvider)"), }) @Entity @Table(name="USER_CONSENT_PROT_MAPPER") diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserConsentRoleEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserConsentRoleEntity.java index 95d5f3e09a..c4818c783e 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserConsentRoleEntity.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserConsentRoleEntity.java @@ -38,6 +38,8 @@ import java.io.Serializable; @NamedQuery(name="deleteUserConsentRolesByUser", query="delete from UserConsentRoleEntity grantedRole where grantedRole.userConsent IN (select consent from UserConsentEntity consent where consent.user = :user)"), @NamedQuery(name="deleteUserConsentRolesByRole", query="delete from UserConsentRoleEntity grantedRole where grantedRole.roleId = :roleId)"), @NamedQuery(name="deleteUserConsentRolesByClient", query="delete from UserConsentRoleEntity grantedRole where grantedRole.userConsent IN (select consent from UserConsentEntity consent where consent.clientId = :clientId)"), + @NamedQuery(name="deleteUserConsentRolesByExternalClient", query="delete from UserConsentRoleEntity grantedRole where grantedRole.userConsent IN (select consent from UserConsentEntity consent where consent.clientStorageProvider = :clientStorageProvider and consent.externalClientId = :externalClientId)"), + @NamedQuery(name="deleteUserConsentRolesByClientStorageProvider", query="delete from UserConsentRoleEntity grantedRole where grantedRole.userConsent IN (select consent from UserConsentEntity consent where consent.clientStorageProvider = :clientStorageProvider)"), }) @Entity @Table(name="USER_CONSENT_ROLE") diff --git a/model/jpa/src/main/java/org/keycloak/storage/jpa/JpaUserFederatedStorageProvider.java b/model/jpa/src/main/java/org/keycloak/storage/jpa/JpaUserFederatedStorageProvider.java index f6de4312a3..7474155630 100644 --- a/model/jpa/src/main/java/org/keycloak/storage/jpa/JpaUserFederatedStorageProvider.java +++ b/model/jpa/src/main/java/org/keycloak/storage/jpa/JpaUserFederatedStorageProvider.java @@ -32,9 +32,11 @@ import org.keycloak.models.RealmModel; import org.keycloak.models.RoleModel; import org.keycloak.models.UserConsentModel; import org.keycloak.models.UserModel; +import org.keycloak.models.jpa.entities.UserConsentEntity; import org.keycloak.models.utils.KeycloakModelUtils; import org.keycloak.storage.StorageId; import org.keycloak.storage.UserStorageProvider; +import org.keycloak.storage.client.ClientStorageProvider; import org.keycloak.storage.federated.UserFederatedStorageProvider; import org.keycloak.storage.jpa.entity.BrokerLinkEntity; import org.keycloak.storage.jpa.entity.FederatedUser; @@ -257,7 +259,13 @@ public class JpaUserFederatedStorageProvider implements consentEntity = new FederatedUserConsentEntity(); consentEntity.setId(KeycloakModelUtils.generateId()); consentEntity.setUserId(userId); - consentEntity.setClientId(clientId); + StorageId clientStorageId = new StorageId(clientId); + if (clientStorageId.isLocal()) { + consentEntity.setClientId(clientId); + } else { + consentEntity.setClientStorageProvider(clientStorageId.getProviderId()); + consentEntity.setExternalClientId(clientStorageId.getExternalId()); + } consentEntity.setRealmId(realm.getId()); consentEntity.setStorageProviderId(new StorageId(userId).getProviderId()); long currentTime = Time.currentTimeMillis(); @@ -315,9 +323,16 @@ public class JpaUserFederatedStorageProvider implements } private FederatedUserConsentEntity getGrantedConsentEntity(String userId, String clientId) { - TypedQuery query = em.createNamedQuery("userFederatedConsentByUserAndClient", FederatedUserConsentEntity.class); + StorageId clientStorageId = new StorageId(clientId); + String queryName = clientStorageId.isLocal() ? "userFederatedConsentByUserAndClient" : "userFederatedConsentByUserAndExternalClient"; + TypedQuery query = em.createNamedQuery(queryName, FederatedUserConsentEntity.class); query.setParameter("userId", userId); - query.setParameter("clientId", clientId); + if (clientStorageId.isLocal()) { + query.setParameter("clientId", clientId); + } else { + query.setParameter("clientStorageProvider", clientStorageId.getProviderId()); + query.setParameter("externalClientId", clientStorageId.getExternalId()); + } List results = query.getResultList(); if (results.size() > 1) { throw new ModelException("More results found for user [" + userId + "] and client [" + clientId + "]"); @@ -334,10 +349,14 @@ public class JpaUserFederatedStorageProvider implements return null; } - ClientModel client = realm.getClientById(entity.getClientId()); - if (client == null) { - throw new ModelException("Client with id " + entity.getClientId() + " is not available"); + StorageId clientStorageId = null; + if ( entity.getClientId() == null) { + clientStorageId = new StorageId(entity.getClientStorageProvider(), entity.getExternalClientId()); + } else { + clientStorageId = new StorageId(entity.getClientId()); } + + ClientModel client = realm.getClientById(clientStorageId.getId()); UserConsentModel model = new UserConsentModel(client); model.setCreatedDate(entity.getCreatedDate()); model.setLastUpdatedDate(entity.getLastUpdatedDate()); @@ -822,9 +841,26 @@ public class JpaUserFederatedStorageProvider implements @Override public void preRemove(RealmModel realm, ClientModel client) { - em.createNamedQuery("deleteFederatedUserConsentProtMappersByClient").setParameter("clientId", client.getId()).executeUpdate(); - em.createNamedQuery("deleteFederatedUserConsentRolesByClient").setParameter("clientId", client.getId()).executeUpdate(); - em.createNamedQuery("deleteFederatedUserConsentsByClient").setParameter("clientId", client.getId()).executeUpdate(); + StorageId clientStorageId = new StorageId(client.getId()); + if (clientStorageId.isLocal()) { + em.createNamedQuery("deleteFederatedUserConsentProtMappersByClient").setParameter("clientId", client.getId()).executeUpdate(); + em.createNamedQuery("deleteFederatedUserConsentRolesByClient").setParameter("clientId", client.getId()).executeUpdate(); + em.createNamedQuery("deleteFederatedUserConsentsByClient").setParameter("clientId", client.getId()).executeUpdate(); + } else { + em.createNamedQuery("deleteFederatedUserConsentProtMappersByExternalClient") + .setParameter("clientStorageProvider", clientStorageId.getProviderId()) + .setParameter("externalClientId",clientStorageId.getExternalId()) + .executeUpdate(); + em.createNamedQuery("deleteFederatedUserConsentRolesByExternalClient") + .setParameter("clientStorageProvider", clientStorageId.getProviderId()) + .setParameter("externalClientId",clientStorageId.getExternalId()) + .executeUpdate(); + em.createNamedQuery("deleteFederatedUserConsentsByExternalClient") + .setParameter("clientStorageProvider", clientStorageId.getProviderId()) + .setParameter("externalClientId",clientStorageId.getExternalId()) + .executeUpdate(); + + } } @Override @@ -885,41 +921,53 @@ public class JpaUserFederatedStorageProvider implements @Override public void preRemove(RealmModel realm, ComponentModel model) { - if (!model.getProviderType().equals(UserStorageProvider.class.getName())) return; + if (model.getProviderType().equals(UserStorageProvider.class.getName())) { - em.createNamedQuery("deleteBrokerLinkByStorageProvider") - .setParameter("storageProviderId", model.getId()) - .executeUpdate(); - em.createNamedQuery("deleteFederatedAttributesByStorageProvider") - .setParameter("storageProviderId", model.getId()) - .executeUpdate(); - em.createNamedQuery("deleteFederatedUserConsentProtMappersByStorageProvider") - .setParameter("storageProviderId", model.getId()) - .executeUpdate(); - em.createNamedQuery("deleteFederatedUserRoleMappingsByStorageProvider") - .setParameter("storageProviderId", model.getId()) - .executeUpdate(); - em.createNamedQuery("deleteFederatedUserConsentsByStorageProvider") - .setParameter("storageProviderId", model.getId()) - .executeUpdate(); - em.createNamedQuery("deleteFederatedCredentialAttributeByStorageProvider") - .setParameter("storageProviderId", model.getId()) - .executeUpdate(); - em.createNamedQuery("deleteFederatedUserCredentialsByStorageProvider") - .setParameter("storageProviderId", model.getId()) - .executeUpdate(); - em.createNamedQuery("deleteFederatedUserGroupMembershipByStorageProvider") - .setParameter("storageProviderId", model.getId()) - .executeUpdate(); - em.createNamedQuery("deleteFederatedUserRequiredActionsByStorageProvider") - .setParameter("storageProviderId", model.getId()) - .executeUpdate(); - em.createNamedQuery("deleteFederatedUserRoleMappingsByStorageProvider") - .setParameter("storageProviderId", model.getId()) - .executeUpdate(); - em.createNamedQuery("deleteFederatedUsersByStorageProvider") - .setParameter("storageProviderId", model.getId()) - .executeUpdate(); + em.createNamedQuery("deleteBrokerLinkByStorageProvider") + .setParameter("storageProviderId", model.getId()) + .executeUpdate(); + em.createNamedQuery("deleteFederatedAttributesByStorageProvider") + .setParameter("storageProviderId", model.getId()) + .executeUpdate(); + em.createNamedQuery("deleteFederatedUserConsentProtMappersByStorageProvider") + .setParameter("storageProviderId", model.getId()) + .executeUpdate(); + em.createNamedQuery("deleteFederatedUserRoleMappingsByStorageProvider") + .setParameter("storageProviderId", model.getId()) + .executeUpdate(); + em.createNamedQuery("deleteFederatedUserConsentsByStorageProvider") + .setParameter("storageProviderId", model.getId()) + .executeUpdate(); + em.createNamedQuery("deleteFederatedCredentialAttributeByStorageProvider") + .setParameter("storageProviderId", model.getId()) + .executeUpdate(); + em.createNamedQuery("deleteFederatedUserCredentialsByStorageProvider") + .setParameter("storageProviderId", model.getId()) + .executeUpdate(); + em.createNamedQuery("deleteFederatedUserGroupMembershipByStorageProvider") + .setParameter("storageProviderId", model.getId()) + .executeUpdate(); + em.createNamedQuery("deleteFederatedUserRequiredActionsByStorageProvider") + .setParameter("storageProviderId", model.getId()) + .executeUpdate(); + em.createNamedQuery("deleteFederatedUserRoleMappingsByStorageProvider") + .setParameter("storageProviderId", model.getId()) + .executeUpdate(); + em.createNamedQuery("deleteFederatedUsersByStorageProvider") + .setParameter("storageProviderId", model.getId()) + .executeUpdate(); + } else if (model.getProviderType().equals(ClientStorageProvider.class.getName())) { + em.createNamedQuery("deleteFederatedUserConsentProtMappersByClientStorageProvider") + .setParameter("clientStorageProvider", model.getId()) + .executeUpdate(); + em.createNamedQuery("deleteFederatedUserConsentRolesByClientStorageProvider") + .setParameter("clientStorageProvider", model.getId()) + .executeUpdate(); + em.createNamedQuery("deleteFederatedUserConsentsByClientStorageProvider") + .setParameter("clientStorageProvider", model.getId()) + .executeUpdate(); + + } } } diff --git a/model/jpa/src/main/java/org/keycloak/storage/jpa/entity/FederatedUserConsentEntity.java b/model/jpa/src/main/java/org/keycloak/storage/jpa/entity/FederatedUserConsentEntity.java index 225e80bd72..c2eac0ba39 100755 --- a/model/jpa/src/main/java/org/keycloak/storage/jpa/entity/FederatedUserConsentEntity.java +++ b/model/jpa/src/main/java/org/keycloak/storage/jpa/entity/FederatedUserConsentEntity.java @@ -40,11 +40,14 @@ import java.util.Collection; }) @NamedQueries({ @NamedQuery(name="userFederatedConsentByUserAndClient", query="select consent from FederatedUserConsentEntity consent where consent.userId = :userId and consent.clientId = :clientId"), + @NamedQuery(name="userFederatedConsentByUserAndExternalClient", query="select consent from FederatedUserConsentEntity consent where consent.userId = :userId and consent.clientStorageProvider = :clientStorageProvider and consent.externalClientId = :externalClientId"), @NamedQuery(name="userFederatedConsentsByUser", query="select consent from FederatedUserConsentEntity consent where consent.userId = :userId"), @NamedQuery(name="deleteFederatedUserConsentsByRealm", query="delete from FederatedUserConsentEntity consent where consent.realmId=:realmId"), @NamedQuery(name="deleteFederatedUserConsentsByStorageProvider", query="delete from FederatedUserConsentEntity e where e.storageProviderId=:storageProviderId"), @NamedQuery(name="deleteFederatedUserConsentsByUser", query="delete from FederatedUserConsentEntity consent where consent.userId = :userId and consent.realmId = :realmId"), @NamedQuery(name="deleteFederatedUserConsentsByClient", query="delete from FederatedUserConsentEntity consent where consent.clientId = :clientId"), + @NamedQuery(name="deleteFederatedUserConsentsByExternalClient", query="delete from FederatedUserConsentEntity consent where consent.clientStorageProvider = :clientStorageProvider and consent.externalClientId = :externalClientId"), + @NamedQuery(name="deleteFederatedUserConsentsByClientStorageProvider", query="delete from FederatedUserConsentEntity consent where consent.clientStorageProvider = :clientStorageProvider"), }) public class FederatedUserConsentEntity { @@ -65,6 +68,12 @@ public class FederatedUserConsentEntity { @Column(name="CLIENT_ID") protected String clientId; + @Column(name="CLIENT_STORAGE_PROVIDER") + protected String clientStorageProvider; + + @Column(name="EXTERNAL_CLIENT_ID") + protected String externalClientId; + @Column(name = "CREATED_DATE") private Long createdDate; @@ -119,6 +128,22 @@ public class FederatedUserConsentEntity { this.clientId = clientId; } + public String getClientStorageProvider() { + return clientStorageProvider; + } + + public void setClientStorageProvider(String clientStorageProvider) { + this.clientStorageProvider = clientStorageProvider; + } + + public String getExternalClientId() { + return externalClientId; + } + + public void setExternalClientId(String externalClientId) { + this.externalClientId = externalClientId; + } + public Collection getGrantedRoles() { return grantedRoles; } diff --git a/model/jpa/src/main/java/org/keycloak/storage/jpa/entity/FederatedUserConsentProtocolMapperEntity.java b/model/jpa/src/main/java/org/keycloak/storage/jpa/entity/FederatedUserConsentProtocolMapperEntity.java index f7da2cc310..a9de2c6b58 100755 --- a/model/jpa/src/main/java/org/keycloak/storage/jpa/entity/FederatedUserConsentProtocolMapperEntity.java +++ b/model/jpa/src/main/java/org/keycloak/storage/jpa/entity/FederatedUserConsentProtocolMapperEntity.java @@ -39,6 +39,8 @@ import java.io.Serializable; @NamedQuery(name="deleteFederatedUserConsentProtMappersByStorageProvider", query="delete from FederatedUserConsentProtocolMapperEntity csm where csm.userConsent IN (select consent from FederatedUserConsentEntity consent where consent.storageProviderId = :storageProviderId)"), @NamedQuery(name="deleteFederatedUserConsentProtMappersByProtocolMapper", query="delete from FederatedUserConsentProtocolMapperEntity csm where csm.protocolMapperId = :protocolMapperId"), @NamedQuery(name="deleteFederatedUserConsentProtMappersByClient", query="delete from FederatedUserConsentProtocolMapperEntity csm where csm.userConsent IN (select consent from FederatedUserConsentEntity consent where consent.clientId = :clientId)"), + @NamedQuery(name="deleteFederatedUserConsentProtMappersByExternalClient", query="delete from FederatedUserConsentProtocolMapperEntity csm where csm.userConsent IN (select consent from FederatedUserConsentEntity consent where consent.clientStorageProvider = :clientStorageProvider and consent.externalClientId = :externalClientId)"), + @NamedQuery(name="deleteFederatedUserConsentProtMappersByClientStorageProvider", query="delete from FederatedUserConsentProtocolMapperEntity csm where csm.userConsent IN (select consent from FederatedUserConsentEntity consent where consent.clientStorageProvider = :clientStorageProvider)"), }) @Entity @Table(name="FED_USER_CONSENT_PROT_MAPPER") diff --git a/model/jpa/src/main/java/org/keycloak/storage/jpa/entity/FederatedUserConsentRoleEntity.java b/model/jpa/src/main/java/org/keycloak/storage/jpa/entity/FederatedUserConsentRoleEntity.java index d74865d11d..0e0551d918 100755 --- a/model/jpa/src/main/java/org/keycloak/storage/jpa/entity/FederatedUserConsentRoleEntity.java +++ b/model/jpa/src/main/java/org/keycloak/storage/jpa/entity/FederatedUserConsentRoleEntity.java @@ -38,6 +38,8 @@ import java.io.Serializable; @NamedQuery(name="deleteFederatedUserConsentRolesByStorageProvider", query="delete from FederatedUserConsentRoleEntity grantedRole where grantedRole.userConsent IN (select consent from FederatedUserConsentEntity consent where consent.storageProviderId = :storageProviderId)"), @NamedQuery(name="deleteFederatedUserConsentRolesByRole", query="delete from FederatedUserConsentRoleEntity grantedRole where grantedRole.roleId = :roleId"), @NamedQuery(name="deleteFederatedUserConsentRolesByClient", query="delete from FederatedUserConsentRoleEntity grantedRole where grantedRole.userConsent IN (select consent from FederatedUserConsentEntity consent where consent.clientId = :clientId)"), + @NamedQuery(name="deleteFederatedUserConsentRolesByExternalClient", query="delete from FederatedUserConsentRoleEntity grantedRole where grantedRole.userConsent IN (select consent from FederatedUserConsentEntity consent where consent.clientStorageProvider = :clientStorageProvider and consent.externalClientId = :externalClientId)"), + @NamedQuery(name="deleteFederatedUserConsentRolesByClientStorageProvider", query="delete from FederatedUserConsentRoleEntity grantedRole where grantedRole.userConsent IN (select consent from FederatedUserConsentEntity consent where consent.clientStorageProvider = :clientStorageProvider)"), }) @Entity @Table(name="FED_USER_CONSENT_ROLE") diff --git a/model/jpa/src/main/resources/META-INF/jpa-changelog-4.0.0.xml b/model/jpa/src/main/resources/META-INF/jpa-changelog-4.0.0.xml index 859f2a7b85..09a1d800a2 100644 --- a/model/jpa/src/main/resources/META-INF/jpa-changelog-4.0.0.xml +++ b/model/jpa/src/main/resources/META-INF/jpa-changelog-4.0.0.xml @@ -41,8 +41,32 @@ - - + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -53,12 +77,5 @@ - - - - - - - - + diff --git a/services/src/main/java/org/keycloak/storage/UserStorageManager.java b/services/src/main/java/org/keycloak/storage/UserStorageManager.java index 16d14e08f1..48015536d9 100755 --- a/services/src/main/java/org/keycloak/storage/UserStorageManager.java +++ b/services/src/main/java/org/keycloak/storage/UserStorageManager.java @@ -40,6 +40,7 @@ import org.keycloak.models.cache.UserCache; import org.keycloak.models.utils.ComponentUtil; import org.keycloak.models.utils.ReadOnlyUserModelDelegate; import org.keycloak.services.managers.UserStorageSyncManager; +import org.keycloak.storage.client.ClientStorageProvider; import org.keycloak.storage.federated.UserFederatedStorageProvider; import org.keycloak.storage.user.ImportedUserValidation; import org.keycloak.storage.user.UserBulkUpdateProvider; @@ -696,6 +697,11 @@ public class UserStorageManager implements UserProvider, OnUserCache, OnCreateCo @Override public void preRemove(RealmModel realm, ComponentModel component) { + if (component.getProviderType().equals(ClientStorageProvider.class.getName())) { + localStorage().preRemove(realm, component); + if (getFederatedStorage() != null) getFederatedStorage().preRemove(realm, component); + return; + } if (!component.getProviderType().equals(UserStorageProvider.class.getName())) return; localStorage().preRemove(realm, component); if (getFederatedStorage() != null) getFederatedStorage().preRemove(realm, component); diff --git a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/federation/HardcodedClientStorageProvider.java b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/federation/HardcodedClientStorageProvider.java index e56c8645a9..672cb1e870 100644 --- a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/federation/HardcodedClientStorageProvider.java +++ b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/federation/HardcodedClientStorageProvider.java @@ -42,12 +42,14 @@ public class HardcodedClientStorageProvider implements ClientStorageProvider, Cl protected ClientStorageProviderModel component; protected String clientId; protected String redirectUri; + protected boolean consent; public HardcodedClientStorageProvider(KeycloakSession session, ClientStorageProviderModel component) { this.session = session; this.component = component; this.clientId = component.getConfig().getFirst(HardcodedClientStorageProviderFactory.CLIENT_ID); this.redirectUri = component.getConfig().getFirst(HardcodedClientStorageProviderFactory.REDIRECT_URI); + this.consent = "true".equals(component.getConfig().getFirst(HardcodedClientStorageProviderFactory.CONSENT)); } @Override @@ -189,7 +191,7 @@ public class HardcodedClientStorageProvider implements ClientStorageProvider, Cl @Override public boolean isConsentRequired() { - return false; + return consent; } @Override diff --git a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/federation/HardcodedClientStorageProviderFactory.java b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/federation/HardcodedClientStorageProviderFactory.java index 6b2e480ffa..67fcc0e52d 100644 --- a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/federation/HardcodedClientStorageProviderFactory.java +++ b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/federation/HardcodedClientStorageProviderFactory.java @@ -48,6 +48,7 @@ public class HardcodedClientStorageProviderFactory implements ClientStorageProvi public static final String CLIENT_ID = "client_id"; public static final String REDIRECT_URI = "redirect_uri"; + public static final String CONSENT = "consent"; static { CONFIG_PROPERTIES = ProviderConfigurationBuilder.create() @@ -58,11 +59,17 @@ public class HardcodedClientStorageProviderFactory implements ClientStorageProvi .defaultValue("hardcoded-client") .add() .property().name(REDIRECT_URI) - .type(ProviderConfigProperty.BOOLEAN_TYPE) + .type(ProviderConfigProperty.STRING_TYPE) .label("Redirect Uri") .helpText("Valid redirect uri. Only one allowed") .defaultValue("http://localhost:8180/*") .add() + .property().name(CONSENT) + .type(ProviderConfigProperty.BOOLEAN_TYPE) + .label("Consent Required") + .helpText("Is consent required") + .defaultValue("false") + .add() .build(); } diff --git a/testsuite/integration-deprecated/src/test/java/org/keycloak/testsuite/model/UserConsentModelTest.java b/testsuite/integration-deprecated/src/test/java/org/keycloak/testsuite/model/UserConsentModelTest.java index 9fe49f21da..ced16a0791 100644 --- a/testsuite/integration-deprecated/src/test/java/org/keycloak/testsuite/model/UserConsentModelTest.java +++ b/testsuite/integration-deprecated/src/test/java/org/keycloak/testsuite/model/UserConsentModelTest.java @@ -20,6 +20,7 @@ package org.keycloak.testsuite.model; import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import org.keycloak.component.ComponentModel; import org.keycloak.models.ClientModel; import org.keycloak.models.ModelException; import org.keycloak.models.ProtocolMapperModel; @@ -30,6 +31,8 @@ import org.keycloak.models.UserConsentModel; import org.keycloak.models.UserModel; import org.keycloak.protocol.oidc.OIDCLoginProtocol; import org.keycloak.protocol.oidc.mappers.UserPropertyMapper; +import org.keycloak.storage.client.ClientStorageProviderModel; +import org.keycloak.testsuite.federation.HardcodedClientStorageProviderFactory; import java.util.List; @@ -38,6 +41,8 @@ import java.util.List; */ public class UserConsentModelTest extends AbstractModelTest { + private ComponentModel clientStorageComponent; + @Before public void setupEnv() { RealmModel realm = realmManager.createRealm("original"); @@ -87,6 +92,22 @@ public class UserConsentModelTest extends AbstractModelTest { maryFooGrant.addGrantedProtocolMapper(fooMapper); realmManager.getSession().users().addConsent(realm, mary.getId(), maryFooGrant); + ClientStorageProviderModel clientStorage = new ClientStorageProviderModel(); + clientStorage.setProviderId(HardcodedClientStorageProviderFactory.PROVIDER_ID); + clientStorage.getConfig().putSingle(HardcodedClientStorageProviderFactory.CLIENT_ID, "hardcoded-client"); + clientStorage.getConfig().putSingle(HardcodedClientStorageProviderFactory.REDIRECT_URI, "http://localhost:8081/*"); + clientStorage.getConfig().putSingle(HardcodedClientStorageProviderFactory.CONSENT, "true"); + clientStorage.setParentId(realm.getId()); + clientStorageComponent = realm.addComponentModel(clientStorage); + + ClientModel hardcodedClient = session.realms().getClientByClientId("hardcoded-client", realm); + + Assert.assertNotNull(hardcodedClient); + + UserConsentModel maryHardcodedGrant = new UserConsentModel(hardcodedClient); + realmManager.getSession().users().addConsent(realm, mary.getId(), maryHardcodedGrant); + + commit(); } @@ -125,7 +146,15 @@ public class UserConsentModelTest extends AbstractModelTest { Assert.assertNotNull("Created Date should be set", maryConsent.getCreatedDate()); Assert.assertNotNull("Last Updated Date should be set", maryConsent.getLastUpdatedDate()); + ClientModel hardcodedClient = session.realms().getClientByClientId("hardcoded-client", realm); + UserConsentModel maryHardcodedConsent = realmManager.getSession().users().getConsentByClient(realm, mary.getId(), hardcodedClient.getId()); + Assert.assertEquals(maryHardcodedConsent.getGrantedRoles().size(), 0); + Assert.assertEquals(maryHardcodedConsent.getGrantedProtocolMappers().size(), 0); + Assert.assertNotNull("Created Date should be set", maryHardcodedConsent.getCreatedDate()); + Assert.assertNotNull("Last Updated Date should be set", maryHardcodedConsent.getLastUpdatedDate()); + Assert.assertNull(realmManager.getSession().users().getConsentByClient(realm, mary.getId(), barClient.getId())); + Assert.assertNull(realmManager.getSession().users().getConsentByClient(realm, john.getId(), hardcodedClient.getId())); } @Test @@ -139,14 +168,26 @@ public class UserConsentModelTest extends AbstractModelTest { List johnConsents = realmManager.getSession().users().getConsents(realm, john.getId()); Assert.assertEquals(2, johnConsents.size()); + ClientModel hardcodedClient = session.realms().getClientByClientId("hardcoded-client", realm); + List maryConsents = realmManager.getSession().users().getConsents(realm, mary.getId()); - Assert.assertEquals(1, maryConsents.size()); + Assert.assertEquals(2, maryConsents.size()); UserConsentModel maryConsent = maryConsents.get(0); + UserConsentModel maryHardcodedConsent = maryConsents.get(1); + if (maryConsents.get(0).getClient().getId().equals(hardcodedClient.getId())) { + maryConsent = maryConsents.get(1); + maryHardcodedConsent = maryConsents.get(0); + + } Assert.assertEquals(maryConsent.getClient().getId(), fooClient.getId()); Assert.assertEquals(maryConsent.getGrantedRoles().size(), 1); Assert.assertEquals(maryConsent.getGrantedProtocolMappers().size(), 1); Assert.assertTrue(isRoleGranted(realm, "realm-role", maryConsent)); Assert.assertTrue(isMapperGranted(fooClient, "foo", maryConsent)); + + Assert.assertEquals(maryHardcodedConsent.getClient().getId(), hardcodedClient.getId()); + Assert.assertEquals(maryHardcodedConsent.getGrantedRoles().size(), 0); + Assert.assertEquals(maryHardcodedConsent.getGrantedProtocolMappers().size(), 0); } @Test @@ -190,14 +231,19 @@ public class UserConsentModelTest extends AbstractModelTest { RealmModel realm = realmManager.getRealm("original"); ClientModel fooClient = realm.getClientByClientId("foo-client"); UserModel john = session.users().getUserByUsername("john", realm); + UserModel mary = session.users().getUserByUsername("mary", realm); realmManager.getSession().users().revokeConsentForClient(realm, john.getId(), fooClient.getId()); + ClientModel hardcodedClient = session.realms().getClientByClientId("hardcoded-client", realm); + realmManager.getSession().users().revokeConsentForClient(realm, mary.getId(), hardcodedClient.getId()); commit(); realm = realmManager.getRealm("original"); john = session.users().getUserByUsername("john", realm); Assert.assertNull(realmManager.getSession().users().getConsentByClient(realm, john.getId(), fooClient.getId())); + mary = session.users().getUserByUsername("mary", realm); + Assert.assertNull(realmManager.getSession().users().getConsentByClient(realm, mary.getId(), hardcodedClient.getId())); } @Test @@ -206,6 +252,8 @@ public class UserConsentModelTest extends AbstractModelTest { RealmModel realm = realmManager.getRealm("original"); UserModel john = session.users().getUserByUsername("john", realm); session.users().removeUser(realm, john); + UserModel mary = session.users().getUserByUsername("mary", realm); + session.users().removeUser(realm, mary); } @Test @@ -270,6 +318,24 @@ public class UserConsentModelTest extends AbstractModelTest { Assert.assertNull(realmManager.getSession().users().getConsentByClient(realm, john.getId(), barClient.getId())); } + @Test + public void deleteClientStorageTest() { + RealmModel realm = realmManager.getRealm("original"); + realm.removeComponent(clientStorageComponent); + commit(); + + + + realm = realmManager.getRealm("original"); + ClientModel hardcodedClient = session.realms().getClientByClientId("hardcoded-client", realm); + Assert.assertNull(hardcodedClient); + + UserModel mary = session.users().getUserByUsername("mary", realm); + + List maryConsents = realmManager.getSession().users().getConsents(realm, mary.getId()); + Assert.assertEquals(1, maryConsents.size()); + } + private boolean isRoleGranted(RoleContainerModel roleContainer, String roleName, UserConsentModel consentModel) { RoleModel role = roleContainer.getRole(roleName); return consentModel.isRoleGranted(role); diff --git a/testsuite/integration-deprecated/src/test/java/org/keycloak/testsuite/model/UserConsentWithUserStorageModelTest.java b/testsuite/integration-deprecated/src/test/java/org/keycloak/testsuite/model/UserConsentWithUserStorageModelTest.java index 6fd18bf946..04b5cdeb4c 100644 --- a/testsuite/integration-deprecated/src/test/java/org/keycloak/testsuite/model/UserConsentWithUserStorageModelTest.java +++ b/testsuite/integration-deprecated/src/test/java/org/keycloak/testsuite/model/UserConsentWithUserStorageModelTest.java @@ -20,6 +20,7 @@ package org.keycloak.testsuite.model; import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import org.keycloak.component.ComponentModel; import org.keycloak.models.ClientModel; import org.keycloak.models.ModelException; import org.keycloak.models.ProtocolMapperModel; @@ -31,6 +32,8 @@ import org.keycloak.models.UserModel; import org.keycloak.protocol.oidc.OIDCLoginProtocol; import org.keycloak.protocol.oidc.mappers.UserPropertyMapper; import org.keycloak.storage.UserStorageProviderModel; +import org.keycloak.storage.client.ClientStorageProviderModel; +import org.keycloak.testsuite.federation.HardcodedClientStorageProviderFactory; import org.keycloak.testsuite.federation.storage.UserMapStorageFactory; import org.keycloak.testsuite.federation.storage.UserPropertyFileStorageFactory; @@ -41,6 +44,8 @@ import java.util.List; */ public class UserConsentWithUserStorageModelTest extends AbstractModelTest { + private ComponentModel clientStorageComponent; + @Before public void setupEnv() { RealmModel realm = realmManager.createRealm("original"); @@ -97,6 +102,22 @@ public class UserConsentWithUserStorageModelTest extends AbstractModelTest { maryFooGrant.addGrantedProtocolMapper(fooMapper); realmManager.getSession().users().addConsent(realm, mary.getId(), maryFooGrant); + ClientStorageProviderModel clientStorage = new ClientStorageProviderModel(); + clientStorage.setProviderId(HardcodedClientStorageProviderFactory.PROVIDER_ID); + clientStorage.getConfig().putSingle(HardcodedClientStorageProviderFactory.CLIENT_ID, "hardcoded-client"); + clientStorage.getConfig().putSingle(HardcodedClientStorageProviderFactory.REDIRECT_URI, "http://localhost:8081/*"); + clientStorage.getConfig().putSingle(HardcodedClientStorageProviderFactory.CONSENT, "true"); + clientStorage.setParentId(realm.getId()); + clientStorageComponent = realm.addComponentModel(clientStorage); + + ClientModel hardcodedClient = session.realms().getClientByClientId("hardcoded-client", realm); + + Assert.assertNotNull(hardcodedClient); + + UserConsentModel maryHardcodedGrant = new UserConsentModel(hardcodedClient); + realmManager.getSession().users().addConsent(realm, mary.getId(), maryHardcodedGrant); + + commit(); } @@ -135,7 +156,15 @@ public class UserConsentWithUserStorageModelTest extends AbstractModelTest { Assert.assertNotNull("Created Date should be set", maryConsent.getCreatedDate()); Assert.assertNotNull("Last Updated Date should be set", maryConsent.getLastUpdatedDate()); + ClientModel hardcodedClient = session.realms().getClientByClientId("hardcoded-client", realm); + UserConsentModel maryHardcodedConsent = realmManager.getSession().users().getConsentByClient(realm, mary.getId(), hardcodedClient.getId()); + Assert.assertEquals(maryHardcodedConsent.getGrantedRoles().size(), 0); + Assert.assertEquals(maryHardcodedConsent.getGrantedProtocolMappers().size(), 0); + Assert.assertNotNull("Created Date should be set", maryHardcodedConsent.getCreatedDate()); + Assert.assertNotNull("Last Updated Date should be set", maryHardcodedConsent.getLastUpdatedDate()); + Assert.assertNull(realmManager.getSession().users().getConsentByClient(realm, mary.getId(), barClient.getId())); + Assert.assertNull(realmManager.getSession().users().getConsentByClient(realm, john.getId(), hardcodedClient.getId())); } @Test @@ -149,14 +178,26 @@ public class UserConsentWithUserStorageModelTest extends AbstractModelTest { List johnConsents = realmManager.getSession().users().getConsents(realm, john.getId()); Assert.assertEquals(2, johnConsents.size()); + ClientModel hardcodedClient = session.realms().getClientByClientId("hardcoded-client", realm); + List maryConsents = realmManager.getSession().users().getConsents(realm, mary.getId()); - Assert.assertEquals(1, maryConsents.size()); + Assert.assertEquals(2, maryConsents.size()); UserConsentModel maryConsent = maryConsents.get(0); + UserConsentModel maryHardcodedConsent = maryConsents.get(1); + if (maryConsents.get(0).getClient().getId().equals(hardcodedClient.getId())) { + maryConsent = maryConsents.get(1); + maryHardcodedConsent = maryConsents.get(0); + + } Assert.assertEquals(maryConsent.getClient().getId(), fooClient.getId()); Assert.assertEquals(maryConsent.getGrantedRoles().size(), 1); Assert.assertEquals(maryConsent.getGrantedProtocolMappers().size(), 1); Assert.assertTrue(isRoleGranted(realm, "realm-role", maryConsent)); Assert.assertTrue(isMapperGranted(fooClient, "foo", maryConsent)); + + Assert.assertEquals(maryHardcodedConsent.getClient().getId(), hardcodedClient.getId()); + Assert.assertEquals(maryHardcodedConsent.getGrantedRoles().size(), 0); + Assert.assertEquals(maryHardcodedConsent.getGrantedProtocolMappers().size(), 0); } @Test @@ -200,14 +241,19 @@ public class UserConsentWithUserStorageModelTest extends AbstractModelTest { RealmModel realm = realmManager.getRealm("original"); ClientModel fooClient = realm.getClientByClientId("foo-client"); UserModel john = session.users().getUserByUsername("john", realm); + UserModel mary = session.users().getUserByUsername("mary", realm); realmManager.getSession().users().revokeConsentForClient(realm, john.getId(), fooClient.getId()); + ClientModel hardcodedClient = session.realms().getClientByClientId("hardcoded-client", realm); + realmManager.getSession().users().revokeConsentForClient(realm, mary.getId(), hardcodedClient.getId()); commit(); realm = realmManager.getRealm("original"); john = session.users().getUserByUsername("john", realm); Assert.assertNull(realmManager.getSession().users().getConsentByClient(realm, john.getId(), fooClient.getId())); + mary = session.users().getUserByUsername("mary", realm); + Assert.assertNull(realmManager.getSession().users().getConsentByClient(realm, mary.getId(), hardcodedClient.getId())); } @Test @@ -216,6 +262,8 @@ public class UserConsentWithUserStorageModelTest extends AbstractModelTest { RealmModel realm = realmManager.getRealm("original"); UserModel john = session.users().getUserByUsername("john", realm); session.users().removeUser(realm, john); + UserModel mary = session.users().getUserByUsername("mary", realm); + session.users().removeUser(realm, mary); } @Test @@ -280,6 +328,24 @@ public class UserConsentWithUserStorageModelTest extends AbstractModelTest { Assert.assertNull(realmManager.getSession().users().getConsentByClient(realm, john.getId(), barClient.getId())); } + @Test + public void deleteClientStorageTest() { + RealmModel realm = realmManager.getRealm("original"); + realm.removeComponent(clientStorageComponent); + commit(); + + + + realm = realmManager.getRealm("original"); + ClientModel hardcodedClient = session.realms().getClientByClientId("hardcoded-client", realm); + Assert.assertNull(hardcodedClient); + + UserModel mary = session.users().getUserByUsername("mary", realm); + + List maryConsents = realmManager.getSession().users().getConsents(realm, mary.getId()); + Assert.assertEquals(1, maryConsents.size()); + } + private boolean isRoleGranted(RoleContainerModel roleContainer, String roleName, UserConsentModel consentModel) { RoleModel role = roleContainer.getRole(roleName); return consentModel.isRoleGranted(role);