keycloak-memoizeit
Changes
connections/mongo/src/main/java/org/keycloak/connections/mongo/api/context/MongoStoreInvocationContext.java 2(+2 -0)
connections/mongo/src/main/java/org/keycloak/connections/mongo/DefaultMongoConnectionFactoryProvider.java 3(+2 -1)
connections/mongo/src/main/java/org/keycloak/connections/mongo/impl/context/SimpleMongoStoreInvocationContext.java 4(+4 -0)
connections/mongo/src/main/java/org/keycloak/connections/mongo/impl/context/TransactionMongoStoreInvocationContext.java 22(+18 -4)
connections/mongo-update/src/main/java/org/keycloak/connections/mongo/updater/impl/updates/Update1_2_0_RC1.java 1(+1 -0)
export-import/export-import-api/src/main/java/org/keycloak/exportimport/util/ExportUtils.java 33(+32 -1)
forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/model/AccessBean.java 14(+6 -8)
model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/UserAdapter.java 22(+11 -11)
model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserConsentProtocolMapperEntity.java 50(+25 -25)
model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoUserProvider.java 46(+35 -11)
model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoClientEntity.java 2(+1 -1)
model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoRealmEntity.java 9(+3 -6)
model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoRoleEntity.java 19(+4 -15)
model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoUserConsentEntity.java 17(+17 -0)
model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoUserEntity.java 10(+9 -1)
model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/entities/MongoUserSessionEntity.java 2(+1 -1)
model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/MongoUserSessionProvider.java 18(+7 -11)
Details
diff --git a/connections/jpa/src/main/resources/META-INF/persistence.xml b/connections/jpa/src/main/resources/META-INF/persistence.xml
index fbea205..b4d93a7 100755
--- a/connections/jpa/src/main/resources/META-INF/persistence.xml
+++ b/connections/jpa/src/main/resources/META-INF/persistence.xml
@@ -20,9 +20,9 @@
<class>org.keycloak.models.jpa.entities.IdentityProviderMapperEntity</class>
<class>org.keycloak.models.jpa.entities.ClientIdentityProviderMappingEntity</class>
<class>org.keycloak.models.jpa.entities.ProtocolMapperEntity</class>
- <class>org.keycloak.models.jpa.entities.GrantedConsentEntity</class>
- <class>org.keycloak.models.jpa.entities.GrantedConsentRoleEntity</class>
- <class>org.keycloak.models.jpa.entities.GrantedConsentProtocolMapperEntity</class>
+ <class>org.keycloak.models.jpa.entities.UserConsentEntity</class>
+ <class>org.keycloak.models.jpa.entities.UserConsentRoleEntity</class>
+ <class>org.keycloak.models.jpa.entities.UserConsentProtocolMapperEntity</class>
<!-- JpaUserSessionProvider -->
<class>org.keycloak.models.sessions.jpa.entities.ClientSessionEntity</class>
diff --git a/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.2.0.RC1.xml b/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.2.0.RC1.xml
index a1698dc..7b8c877 100755
--- a/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.2.0.RC1.xml
+++ b/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.2.0.RC1.xml
@@ -35,7 +35,7 @@
<addColumn tableName="CREDENTIAL">
<column name="CREATED_DATE" type="BIGINT"/>
</addColumn>
- <createTable tableName="GRANTED_CONSENT">
+ <createTable tableName="USER_CONSENT">
<column name="ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
@@ -46,16 +46,16 @@
<constraints nullable="false"/>
</column>
</createTable>
- <createTable tableName="GRANTED_CONSENT_ROLE">
- <column name="GRANTED_CONSENT_ID" type="VARCHAR(36)">
+ <createTable tableName="USER_CONSENT_ROLE">
+ <column name="USER_CONSENT_ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
<column name="ROLE_ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
</createTable>
- <createTable tableName="GRANTED_CONSENT_PROT_MAPPER">
- <column name="GRANTED_CONSENT_ID" type="VARCHAR(36)">
+ <createTable tableName="USER_CONSENT_PROT_MAPPER">
+ <column name="USER_CONSENT_ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
<column name="PROTOCOL_MAPPER_ID" type="VARCHAR(36)">
@@ -64,14 +64,14 @@
</createTable>
<addPrimaryKey columnNames="ID" constraintName="CONSTRAINT_IDPM" tableName="IDENTITY_PROVIDER_MAPPER"/>
<addPrimaryKey columnNames="IDP_MAPPER_ID, NAME" constraintName="CONSTRAINT_IDPMConfig" tableName="IDP_MAPPER_CONFIG"/>
- <addPrimaryKey columnNames="ID" constraintName="CONSTRAINT_GRNTCSNT_PM" tableName="GRANTED_CONSENT"/>
- <addPrimaryKey columnNames="GRANTED_CONSENT_ID, ROLE_ID" constraintName="CONSTRAINT_GRNTCSNT_ROLE_PM" tableName="GRANTED_CONSENT_ROLE"/>
- <addPrimaryKey columnNames="GRANTED_CONSENT_ID, PROTOCOL_MAPPER_ID" constraintName="CONSTRAINT_GRNTCSNT_PRM_PM" tableName="GRANTED_CONSENT_PROT_MAPPER"/>
+ <addPrimaryKey columnNames="ID" constraintName="CONSTRAINT_GRNTCSNT_PM" tableName="USER_CONSENT"/>
+ <addPrimaryKey columnNames="USER_CONSENT_ID, ROLE_ID" constraintName="CONSTRAINT_GRNTCSNT_ROLE_PM" tableName="USER_CONSENT_ROLE"/>
+ <addPrimaryKey columnNames="USER_CONSENT_ID, PROTOCOL_MAPPER_ID" constraintName="CONSTRAINT_GRNTCSNT_PRM_PM" tableName="USER_CONSENT_PROT_MAPPER"/>
<addForeignKeyConstraint baseColumnNames="REALM_ID" baseTableName="IDENTITY_PROVIDER_MAPPER" constraintName="FK_IDPM_REALM" referencedColumnNames="ID" referencedTableName="REALM"/>
<addForeignKeyConstraint baseColumnNames="IDP_MAPPER_ID" baseTableName="IDP_MAPPER_CONFIG" constraintName="FK_IDPMConfig" referencedColumnNames="ID" referencedTableName="IDENTITY_PROVIDER_MAPPER"/>
- <addForeignKeyConstraint baseColumnNames="USER_ID" baseTableName="GRANTED_CONSENT" constraintName="FK_GRNTCSNT_USER" referencedColumnNames="ID" referencedTableName="USER_ENTITY"/>
- <addForeignKeyConstraint baseColumnNames="GRANTED_CONSENT_ID" baseTableName="GRANTED_CONSENT_ROLE" constraintName="FK_GRNTCSNT_ROLE_GR" referencedColumnNames="ID" referencedTableName="GRANTED_CONSENT"/>
- <addForeignKeyConstraint baseColumnNames="GRANTED_CONSENT_ID" baseTableName="GRANTED_CONSENT_PROT_MAPPER" constraintName="FK_GRNTCSNT_PRM_GR" referencedColumnNames="ID" referencedTableName="GRANTED_CONSENT"/>
+ <addForeignKeyConstraint baseColumnNames="USER_ID" baseTableName="USER_CONSENT" constraintName="FK_GRNTCSNT_USER" referencedColumnNames="ID" referencedTableName="USER_ENTITY"/>
+ <addForeignKeyConstraint baseColumnNames="USER_CONSENT_ID" baseTableName="USER_CONSENT_ROLE" constraintName="FK_GRNTCSNT_ROLE_GR" referencedColumnNames="ID" referencedTableName="USER_CONSENT"/>
+ <addForeignKeyConstraint baseColumnNames="USER_CONSENT_ID" baseTableName="USER_CONSENT_PROT_MAPPER" constraintName="FK_GRNTCSNT_PRM_GR" referencedColumnNames="ID" referencedTableName="USER_CONSENT"/>
<addColumn tableName="CLIENT">
<column name="CONSENT_REQUIRED" type="BOOLEAN" defaultValueBoolean="false">
@@ -101,7 +101,7 @@
<dropUniqueConstraint tableName="KEYCLOAK_ROLE" constraintName="UK_J3RWUVD56ONTGSUHOGM184WW2"/>
<addUniqueConstraint columnNames="NAME,CLIENT_REALM_CONSTRAINT" constraintName="UK_J3RWUVD56ONTGSUHOGM184WW2-2" tableName="KEYCLOAK_ROLE"/>
- <addUniqueConstraint columnNames="CLIENT_ID, USER_ID" constraintName="UK_JKUWUVD56ONTGSUHOGM8UEWRT" tableName="GRANTED_CONSENT"/>
+ <addUniqueConstraint columnNames="CLIENT_ID, USER_ID" constraintName="UK_JKUWUVD56ONTGSUHOGM8UEWRT" tableName="USER_CONSENT"/>
</changeSet>
</databaseChangeLog>
diff --git a/connections/mongo/src/main/java/org/keycloak/connections/mongo/api/context/MongoStoreInvocationContext.java b/connections/mongo/src/main/java/org/keycloak/connections/mongo/api/context/MongoStoreInvocationContext.java
index c542ffe..272f1c8 100644
--- a/connections/mongo/src/main/java/org/keycloak/connections/mongo/api/context/MongoStoreInvocationContext.java
+++ b/connections/mongo/src/main/java/org/keycloak/connections/mongo/api/context/MongoStoreInvocationContext.java
@@ -22,6 +22,8 @@ public interface MongoStoreInvocationContext {
void beforeDBSearch(Class<? extends MongoIdentifiableEntity> entityType);
+ void beforeDBBulkUpdateOrRemove(Class<? extends MongoIdentifiableEntity> entityType);
+
void begin();
void commit();
diff --git a/connections/mongo/src/main/java/org/keycloak/connections/mongo/api/MongoStore.java b/connections/mongo/src/main/java/org/keycloak/connections/mongo/api/MongoStore.java
index 36f448c..397c307 100755
--- a/connections/mongo/src/main/java/org/keycloak/connections/mongo/api/MongoStore.java
+++ b/connections/mongo/src/main/java/org/keycloak/connections/mongo/api/MongoStore.java
@@ -24,13 +24,35 @@ public interface MongoStore {
*/
void updateEntity(MongoIdentifiableEntity entity, MongoStoreInvocationContext context);
+ /**
+ * Bulk update of more entities of some type
+ *
+ * @param type
+ * @param query
+ * @param update
+ * @param context
+ * @return count of updated entities
+ */
+ <T extends MongoIdentifiableEntity> int updateEntities(Class<T> type, DBObject query, DBObject update, MongoStoreInvocationContext context);
<T extends MongoIdentifiableEntity> T loadEntity(Class<T> type, String id, MongoStoreInvocationContext context);
<T extends MongoIdentifiableEntity> T loadSingleEntity(Class<T> type, DBObject query, MongoStoreInvocationContext context);
+ /**
+ * @param type
+ * @param query
+ * @param context
+ * @return query result or empty list if no results available for the query. Doesn't return null
+ */
<T extends MongoIdentifiableEntity> List<T> loadEntities(Class<T> type, DBObject query, MongoStoreInvocationContext context);
+ /**
+ * @param type
+ * @param query
+ * @param context
+ * @return query result or empty list if no results available for the query. Doesn't return null
+ */
<T extends MongoIdentifiableEntity> List<T> loadEntities(Class<T> type, DBObject query, DBObject sort, int firstResult, int maxResults, MongoStoreInvocationContext context);
<T extends MongoIdentifiableEntity> int countEntities(Class<T> type, DBObject query, MongoStoreInvocationContext context);
@@ -39,7 +61,16 @@ public interface MongoStore {
boolean removeEntity(Class<? extends MongoIdentifiableEntity> type, String id, MongoStoreInvocationContext context);
- boolean removeEntities(Class<? extends MongoIdentifiableEntity> type, DBObject query, MongoStoreInvocationContext context);
+ /**
+ *
+ * @param type
+ * @param query
+ * @param callback if true, then store will first load all entities, then call "afterRemove" for every entity. If false, the entities are removed directly without load and calling "afterRemove" callback
+ * false has better performance (especially if we are going to remove big number of entities)
+ * @param context
+ * @return count of removed entities
+ */
+ int removeEntities(Class<? extends MongoIdentifiableEntity> type, DBObject query, boolean callback, MongoStoreInvocationContext context);
<S> boolean pushItemToList(MongoIdentifiableEntity entity, String listPropertyName, S itemToPush, boolean skipIfAlreadyPresent, MongoStoreInvocationContext context);
diff --git a/connections/mongo/src/main/java/org/keycloak/connections/mongo/DefaultMongoConnectionFactoryProvider.java b/connections/mongo/src/main/java/org/keycloak/connections/mongo/DefaultMongoConnectionFactoryProvider.java
index 138955b..0ef0069 100755
--- a/connections/mongo/src/main/java/org/keycloak/connections/mongo/DefaultMongoConnectionFactoryProvider.java
+++ b/connections/mongo/src/main/java/org/keycloak/connections/mongo/DefaultMongoConnectionFactoryProvider.java
@@ -38,7 +38,8 @@ public class DefaultMongoConnectionFactoryProvider implements MongoConnectionPro
"org.keycloak.models.sessions.mongo.entities.MongoUserSessionEntity",
"org.keycloak.models.sessions.mongo.entities.MongoClientSessionEntity",
"org.keycloak.models.entities.UserFederationProviderEntity",
- "org.keycloak.models.entities.ProtocolMapperEntity"
+ "org.keycloak.models.entities.ProtocolMapperEntity",
+ "org.keycloak.models.mongo.keycloak.entities.MongoUserConsentEntity"
};
private static final Logger logger = Logger.getLogger(DefaultMongoConnectionFactoryProvider.class);
diff --git a/connections/mongo/src/main/java/org/keycloak/connections/mongo/impl/context/SimpleMongoStoreInvocationContext.java b/connections/mongo/src/main/java/org/keycloak/connections/mongo/impl/context/SimpleMongoStoreInvocationContext.java
index 0ecffc6..868805b 100644
--- a/connections/mongo/src/main/java/org/keycloak/connections/mongo/impl/context/SimpleMongoStoreInvocationContext.java
+++ b/connections/mongo/src/main/java/org/keycloak/connections/mongo/impl/context/SimpleMongoStoreInvocationContext.java
@@ -46,6 +46,10 @@ public class SimpleMongoStoreInvocationContext implements MongoStoreInvocationCo
}
@Override
+ public void beforeDBBulkUpdateOrRemove(Class<? extends MongoIdentifiableEntity> entityType) {
+ }
+
+ @Override
public void begin() {
}
diff --git a/connections/mongo/src/main/java/org/keycloak/connections/mongo/impl/context/TransactionMongoStoreInvocationContext.java b/connections/mongo/src/main/java/org/keycloak/connections/mongo/impl/context/TransactionMongoStoreInvocationContext.java
index 39cf9eb..117f07f 100644
--- a/connections/mongo/src/main/java/org/keycloak/connections/mongo/impl/context/TransactionMongoStoreInvocationContext.java
+++ b/connections/mongo/src/main/java/org/keycloak/connections/mongo/impl/context/TransactionMongoStoreInvocationContext.java
@@ -50,10 +50,6 @@ public class TransactionMongoStoreInvocationContext implements MongoStoreInvocat
@Override
public void addUpdateTask(MongoIdentifiableEntity entityToUpdate, MongoTask task) {
- if (!loadedObjects.containsValue(entityToUpdate)) {
- throw new IllegalStateException("Entity " + entityToUpdate + " not found in loaded objects");
- }
-
Set<MongoTask> currentObjectTasks = pendingUpdateTasks.get(entityToUpdate);
if (currentObjectTasks == null) {
currentObjectTasks = new LinkedHashSet<MongoTask>();
@@ -107,6 +103,24 @@ public class TransactionMongoStoreInvocationContext implements MongoStoreInvocat
}
@Override
+ public void beforeDBBulkUpdateOrRemove(Class<? extends MongoIdentifiableEntity> entityType) {
+ beforeDBSearch(entityType);
+ Set<String> toRemove = new HashSet<String>();
+
+ for (Map.Entry<String, MongoIdentifiableEntity> entry : loadedObjects.entrySet()) {
+ MongoIdentifiableEntity entity = entry.getValue();
+ if (entity.getClass().equals(entityType)) {
+ toRemove.add(entry.getKey());
+ }
+ }
+
+ // Now remove all loadedObjects
+ for (String objectId : toRemove) {
+ loadedObjects.remove(objectId);
+ }
+ }
+
+ @Override
public void begin() {
loadedObjects.clear();
pendingUpdateTasks.clear();
diff --git a/connections/mongo/src/main/java/org/keycloak/connections/mongo/impl/MongoStoreImpl.java b/connections/mongo/src/main/java/org/keycloak/connections/mongo/impl/MongoStoreImpl.java
index aded77e..1696b65 100755
--- a/connections/mongo/src/main/java/org/keycloak/connections/mongo/impl/MongoStoreImpl.java
+++ b/connections/mongo/src/main/java/org/keycloak/connections/mongo/impl/MongoStoreImpl.java
@@ -7,6 +7,7 @@ import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import com.mongodb.MongoException;
+import com.mongodb.WriteResult;
import org.jboss.logging.Logger;
import org.keycloak.connections.mongo.api.MongoCollection;
import org.keycloak.connections.mongo.api.MongoEntity;
@@ -127,7 +128,7 @@ public class MongoStoreImpl implements MongoStore {
throw convertException(e);
}
- // Treat object as created in this transaction (It is already submited to transaction)
+ // Treat object as created in this transaction (It is already submitted to transaction)
context.addCreatedEntity(entity);
}
@@ -170,6 +171,16 @@ public class MongoStoreImpl implements MongoStore {
context.addUpdateTask(entity, fullUpdateTask);
}
+ @Override
+ public <T extends MongoIdentifiableEntity> int updateEntities(Class<T> type, DBObject query, DBObject update, MongoStoreInvocationContext context) {
+ context.beforeDBBulkUpdateOrRemove(type);
+
+ DBCollection collection = getDBCollectionForType(type);
+ WriteResult wr = collection.update(query, update, false, true);
+
+ logger.debugf("Updated %d collections of type %s", wr.getN(), type);
+ return wr.getN();
+ }
@Override
public <T extends MongoIdentifiableEntity> T loadEntity(Class<T> type, String id, MongoStoreInvocationContext context) {
@@ -275,19 +286,32 @@ public class MongoStoreImpl implements MongoStore {
@Override
- public boolean removeEntities(Class<? extends MongoIdentifiableEntity> type, DBObject query, MongoStoreInvocationContext context) {
- List<? extends MongoIdentifiableEntity> foundObjects = loadEntities(type, query, context);
- if (foundObjects.size() == 0) {
- return false;
+ public int removeEntities(Class<? extends MongoIdentifiableEntity> type, DBObject query, boolean callback, MongoStoreInvocationContext context) {
+ if (callback) {
+ List<? extends MongoIdentifiableEntity> foundObjects = loadEntities(type, query, context);
+ if (foundObjects.size() == 0) {
+ return 0;
+ } else {
+ DBCollection dbCollection = getDBCollectionForType(type);
+ dbCollection.remove(query);
+
+ logger.debugf("Removed %d entities of type: %s, query: %s", foundObjects.size(), type, query);
+
+ for (MongoIdentifiableEntity found : foundObjects) {
+ context.addRemovedEntity(found);;
+ }
+ return foundObjects.size();
+ }
} else {
+
+ context.beforeDBBulkUpdateOrRemove(type);
+
DBCollection dbCollection = getDBCollectionForType(type);
- dbCollection.remove(query);
- //logger.debug("Removed %d" + foundObjects.size() + " entities of type: " + type + ", query: " + query);
+ WriteResult writeResult = dbCollection.remove(query);
+ int removedCount = writeResult.getN();
- for (MongoIdentifiableEntity found : foundObjects) {
- context.addRemovedEntity(found);;
- }
- return true;
+ logger.debugf("Removed directly %d entities of type: %s, query: %s", removedCount, type, query);
+ return removedCount;
}
}
diff --git a/connections/mongo-update/src/main/java/org/keycloak/connections/mongo/updater/impl/updates/Update1_2_0_RC1.java b/connections/mongo-update/src/main/java/org/keycloak/connections/mongo/updater/impl/updates/Update1_2_0_RC1.java
index c980067..8ee4db3 100644
--- a/connections/mongo-update/src/main/java/org/keycloak/connections/mongo/updater/impl/updates/Update1_2_0_RC1.java
+++ b/connections/mongo-update/src/main/java/org/keycloak/connections/mongo/updater/impl/updates/Update1_2_0_RC1.java
@@ -22,6 +22,7 @@ public class Update1_2_0_RC1 extends Update {
db.getCollection("realms").update(new BasicDBObject(), new BasicDBObject("$rename", new BasicDBObject("adminAppId", "clientId")), false, true);
+ ensureIndex("userConsents", new String[]{"clientId", "userId"}, true, false);
}
private void convertApplicationsToClients() {
diff --git a/core/src/main/java/org/keycloak/representations/idm/UserConsentRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/UserConsentRepresentation.java
new file mode 100644
index 0000000..113ba84
--- /dev/null
+++ b/core/src/main/java/org/keycloak/representations/idm/UserConsentRepresentation.java
@@ -0,0 +1,28 @@
+package org.keycloak.representations.idm;
+
+import java.util.List;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class UserConsentRepresentation {
+
+ protected List<String> grantedRoles; // points to roleIds
+ protected List<String> grantedProtocolMappers; // points to protocolMapperIds
+
+ public List<String> getGrantedRoles() {
+ return grantedRoles;
+ }
+
+ public void setGrantedRoles(List<String> grantedRoles) {
+ this.grantedRoles = grantedRoles;
+ }
+
+ public List<String> getGrantedProtocolMappers() {
+ return grantedProtocolMappers;
+ }
+
+ public void setGrantedProtocolMappers(List<String> grantedProtocolMappers) {
+ this.grantedProtocolMappers = grantedProtocolMappers;
+ }
+}
diff --git a/core/src/main/java/org/keycloak/representations/idm/UserRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/UserRepresentation.java
index 94a90d9..b9716d3 100755
--- a/core/src/main/java/org/keycloak/representations/idm/UserRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/UserRepresentation.java
@@ -27,6 +27,7 @@ public class UserRepresentation {
protected List<FederatedIdentityRepresentation> federatedIdentities;
protected List<String> realmRoles;
protected Map<String, List<String>> clientRoles;
+ protected Map<String, UserConsentRepresentation> clientConsents;
@Deprecated
protected Map<String, List<String>> applicationRoles;
@@ -176,6 +177,14 @@ public class UserRepresentation {
this.clientRoles = clientRoles;
}
+ public Map<String, UserConsentRepresentation> getClientConsents() {
+ return clientConsents;
+ }
+
+ public void setClientConsents(Map<String, UserConsentRepresentation> clientConsents) {
+ this.clientConsents = clientConsents;
+ }
+
@Deprecated
public Map<String, List<String>> getApplicationRoles() {
return applicationRoles;
diff --git a/export-import/export-import-api/src/main/java/org/keycloak/exportimport/util/ExportUtils.java b/export-import/export-import-api/src/main/java/org/keycloak/exportimport/util/ExportUtils.java
index c404c3d..bccce2d 100755
--- a/export-import/export-import-api/src/main/java/org/keycloak/exportimport/util/ExportUtils.java
+++ b/export-import/export-import-api/src/main/java/org/keycloak/exportimport/util/ExportUtils.java
@@ -8,14 +8,15 @@ import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig;
import org.keycloak.models.ClientModel;
import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleContainerModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.FederatedIdentityModel;
+import org.keycloak.models.UserConsentModel;
import org.keycloak.models.UserCredentialValueModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.utils.ModelToRepresentation;
-import org.keycloak.representations.idm.ApplicationRepresentation;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.CredentialRepresentation;
import org.keycloak.representations.idm.RealmRepresentation;
@@ -23,6 +24,7 @@ import org.keycloak.representations.idm.RoleRepresentation;
import org.keycloak.representations.idm.RolesRepresentation;
import org.keycloak.representations.idm.ScopeMappingRepresentation;
import org.keycloak.representations.idm.FederatedIdentityRepresentation;
+import org.keycloak.representations.idm.UserConsentRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
import java.io.IOException;
@@ -283,6 +285,35 @@ public class ExportUtils {
userRep.setCredentials(credReps);
userRep.setFederationLink(user.getFederationLink());
+ // Grants
+ List<UserConsentModel> consents = user.getConsents();
+ Map<String, UserConsentRepresentation> consentReps = new HashMap<String, UserConsentRepresentation>();
+ for (UserConsentModel consent : consents) {
+ String clientId = consent.getClient().getClientId();
+
+ List<String> grantedProtocolMappers = new LinkedList<String>();
+ for (ProtocolMapperModel protocolMapper : consent.getGrantedProtocolMappers()) {
+ grantedProtocolMappers.add(protocolMapper.getId());
+ }
+
+ List<String> grantedRoles = new LinkedList<String>();
+ for (RoleModel role : consent.getGrantedRoles()) {
+ grantedRoles.add(role.getId());
+ }
+
+
+ if (grantedRoles.size() > 0 || grantedProtocolMappers.size() > 0) {
+ UserConsentRepresentation consentRep = new UserConsentRepresentation();
+ if (grantedRoles.size() > 0) consentRep.setGrantedRoles(grantedRoles);
+ if (grantedProtocolMappers.size() > 0) consentRep.setGrantedProtocolMappers(grantedProtocolMappers);
+ consentReps.put(clientId, consentRep);
+ }
+ }
+
+ if (consentReps.size() > 0) {
+ userRep.setClientConsents(consentReps);
+ }
+
return userRep;
}
diff --git a/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/model/AccessBean.java b/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/model/AccessBean.java
index 58cea2f..67eb4a6 100644
--- a/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/model/AccessBean.java
+++ b/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/model/AccessBean.java
@@ -5,7 +5,7 @@ import java.util.LinkedList;
import java.util.List;
import org.keycloak.models.ClientModel;
-import org.keycloak.models.GrantedConsentModel;
+import org.keycloak.models.UserConsentModel;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
@@ -20,14 +20,13 @@ public class AccessBean {
private List<ClientGrantBean> clientGrants = new LinkedList<ClientGrantBean>();
public AccessBean(RealmModel realm, UserModel user, URI baseUri, String stateChecker) {
- List<GrantedConsentModel> grantedConsents = user.getGrantedConsents();
- for (GrantedConsentModel consent : grantedConsents) {
- ClientModel client = realm.getClientById(consent.getClientId());
+ List<UserConsentModel> grantedConsents = user.getConsents();
+ for (UserConsentModel consent : grantedConsents) {
+ ClientModel client = consent.getClient();
List<RoleModel> realmRolesGranted = new LinkedList<RoleModel>();
MultivaluedHashMap<String, RoleModel> resourceRolesGranted = new MultivaluedHashMap<String, RoleModel>();
- for (String roleId : consent.getGrantedRoles()) {
- RoleModel role = realm.getRoleById(roleId);
+ for (RoleModel role : consent.getGrantedRoles()) {
if (role.getContainer() instanceof RealmModel) {
realmRolesGranted.add(role);
} else {
@@ -36,8 +35,7 @@ public class AccessBean {
}
List<String> claimsGranted = new LinkedList<String>();
- for (String protocolMapperId : consent.getGrantedProtocolMappers()) {
- ProtocolMapperModel protocolMapper = client.getProtocolMapperById(protocolMapperId);
+ for (ProtocolMapperModel protocolMapper : consent.getGrantedProtocolMappers()) {
claimsGranted.add(protocolMapper.getConsentText());
}
diff --git a/model/api/src/main/java/org/keycloak/models/entities/UserConsentEntity.java b/model/api/src/main/java/org/keycloak/models/entities/UserConsentEntity.java
new file mode 100644
index 0000000..47b76c6
--- /dev/null
+++ b/model/api/src/main/java/org/keycloak/models/entities/UserConsentEntity.java
@@ -0,0 +1,47 @@
+package org.keycloak.models.entities;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class UserConsentEntity extends AbstractIdentifiableEntity {
+
+ private String userId;
+ private String clientId;
+ private List<String> grantedRoles = new ArrayList<String>();
+ private List<String> grantedProtocolMappers = new ArrayList<String>();
+
+ public String getUserId() {
+ return userId;
+ }
+
+ public void setUserId(String userId) {
+ this.userId = userId;
+ }
+
+ public String getClientId() {
+ return clientId;
+ }
+
+ public void setClientId(String clientId) {
+ this.clientId = clientId;
+ }
+
+ public List<String> getGrantedRoles() {
+ return grantedRoles;
+ }
+
+ public void setGrantedRoles(List<String> grantedRoles) {
+ this.grantedRoles = grantedRoles;
+ }
+
+ public List<String> getGrantedProtocolMappers() {
+ return grantedProtocolMappers;
+ }
+
+ public void setGrantedProtocolMappers(List<String> grantedProtocolMappers) {
+ this.grantedProtocolMappers = grantedProtocolMappers;
+ }
+}
diff --git a/model/api/src/main/java/org/keycloak/models/UserConsentModel.java b/model/api/src/main/java/org/keycloak/models/UserConsentModel.java
new file mode 100644
index 0000000..11f1034
--- /dev/null
+++ b/model/api/src/main/java/org/keycloak/models/UserConsentModel.java
@@ -0,0 +1,69 @@
+package org.keycloak.models;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class UserConsentModel {
+
+ private final RealmModel realm;
+ private final ClientModel client;
+ private Set<ProtocolMapperModel> protocolMappers = new HashSet<ProtocolMapperModel>();
+ private Set<RoleModel> roles = new HashSet<RoleModel>();
+
+ public UserConsentModel(RealmModel realm, String clientId) {
+ this.realm = realm;
+ this.client = realm.getClientById(clientId);
+
+ if (client == null) {
+ throw new ModelException("Client with id [" + clientId + "] is not available");
+ }
+ }
+
+ public ClientModel getClient() {
+ return client;
+ }
+
+ public void addGrantedRole(String roleId) {
+ RoleModel role = realm.getRoleById(roleId);
+
+ // Chance that role was already deleted by other transaction and is not available anymore
+ if (role != null) {
+ roles.add(role);
+ }
+ }
+
+ public Set<RoleModel> getGrantedRoles() {
+ return roles;
+ }
+
+ public boolean isRoleGranted(RoleModel role) {
+ for (RoleModel currentRole : roles) {
+ if (currentRole.getId().equals(role.getId())) return true;
+ }
+ return false;
+ }
+
+ public void addGrantedProtocolMapper(String protocolMapperId) {
+ ProtocolMapperModel protocolMapper = client.getProtocolMapperById(protocolMapperId);
+
+ // Chance that protocolMapper was already deleted by other transaction and is not available anymore
+ if (protocolMapper != null) {
+ protocolMappers.add(protocolMapper);
+ }
+ }
+
+ public Set<ProtocolMapperModel> getGrantedProtocolMappers() {
+ return protocolMappers;
+ }
+
+ public boolean isProtocolMapperGranted(ProtocolMapperModel protocolMapper) {
+ for (ProtocolMapperModel currentProtMapper : protocolMappers) {
+ if (currentProtMapper.getId().equals(protocolMapper.getId())) return true;
+ }
+ return false;
+ }
+
+}
diff --git a/model/api/src/main/java/org/keycloak/models/UserModel.java b/model/api/src/main/java/org/keycloak/models/UserModel.java
index 6ad716c..ed5ae9e 100755
--- a/model/api/src/main/java/org/keycloak/models/UserModel.java
+++ b/model/api/src/main/java/org/keycloak/models/UserModel.java
@@ -75,11 +75,11 @@ public interface UserModel {
String getFederationLink();
void setFederationLink(String link);
- GrantedConsentModel addGrantedConsent(GrantedConsentModel consent);
- GrantedConsentModel getGrantedConsentByClient(String clientId);
- List<GrantedConsentModel> getGrantedConsents();
- void updateGrantedConsent(GrantedConsentModel consent);
- boolean revokeGrantedConsentForClient(String clientId);
+ void addConsent(UserConsentModel consent);
+ UserConsentModel getConsentByClient(String clientId);
+ List<UserConsentModel> getConsents();
+ void updateConsent(UserConsentModel consent);
+ boolean revokeConsentForClient(String clientId);
public static enum RequiredAction {
VERIFY_EMAIL, UPDATE_PROFILE, CONFIGURE_TOTP, UPDATE_PASSWORD
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 6fc3e1e..0312ff4 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
@@ -16,6 +16,7 @@ import org.keycloak.models.PasswordPolicy;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserConsentModel;
import org.keycloak.models.UserCredentialModel;
import org.keycloak.models.UserCredentialValueModel;
import org.keycloak.models.UserFederationProviderModel;
@@ -34,6 +35,7 @@ import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.representations.idm.RoleRepresentation;
import org.keycloak.representations.idm.ScopeMappingRepresentation;
import org.keycloak.representations.idm.SocialLinkRepresentation;
+import org.keycloak.representations.idm.UserConsentRepresentation;
import org.keycloak.representations.idm.UserFederationProviderRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.util.UriUtils;
@@ -789,6 +791,35 @@ public class RepresentationToModel {
createClientRoleMappings(client, user, entry.getValue());
}
}
+ if (userRep.getClientConsents() != null) {
+ for (Map.Entry<String, UserConsentRepresentation> entry : userRep.getClientConsents().entrySet()) {
+ ClientModel client = clientMap.get(entry.getKey());
+ if (client == null) {
+ throw new RuntimeException("Unable to find client consent mappings for client: " + entry.getKey());
+ }
+
+ UserConsentModel consentModel = new UserConsentModel(newRealm, client.getId());
+
+ UserConsentRepresentation consentRep = entry.getValue();
+ if (consentRep.getGrantedRoles() != null) {
+ for (String roleId : consentRep.getGrantedRoles()) {
+ if (newRealm.getRoleById(roleId) == null) {
+ throw new RuntimeException("Unable to find realm role referenced in consent mappings of user " + user.getUsername() + ". Role ID: " + roleId);
+ }
+ consentModel.addGrantedRole(roleId);
+ }
+ }
+ if (consentRep.getGrantedProtocolMappers() != null) {
+ for (String mapperId : consentRep.getGrantedProtocolMappers()) {
+ if (client.getProtocolMapperById(mapperId) == null) {
+ throw new RuntimeException("Unable to find protocol mapper referenced in consent mappings of user " + user.getUsername() + ". Protocol mapper ID: " + mapperId);
+ }
+ consentModel.addGrantedProtocolMapper(mapperId);;
+ }
+ }
+ user.addConsent(consentModel);
+ }
+ }
return user;
}
diff --git a/model/api/src/main/java/org/keycloak/models/utils/UserModelDelegate.java b/model/api/src/main/java/org/keycloak/models/utils/UserModelDelegate.java
index 83b6add..8ac8f5b 100755
--- a/model/api/src/main/java/org/keycloak/models/utils/UserModelDelegate.java
+++ b/model/api/src/main/java/org/keycloak/models/utils/UserModelDelegate.java
@@ -1,7 +1,7 @@
package org.keycloak.models.utils;
import org.keycloak.models.ClientModel;
-import org.keycloak.models.GrantedConsentModel;
+import org.keycloak.models.UserConsentModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserCredentialModel;
import org.keycloak.models.UserCredentialValueModel;
@@ -188,27 +188,27 @@ public class UserModelDelegate implements UserModel {
}
@Override
- public GrantedConsentModel addGrantedConsent(GrantedConsentModel consent) {
- return delegate.addGrantedConsent(consent);
+ public void addConsent(UserConsentModel consent) {
+ delegate.addConsent(consent);
}
@Override
- public GrantedConsentModel getGrantedConsentByClient(String clientId) {
- return delegate.getGrantedConsentByClient(clientId);
+ public UserConsentModel getConsentByClient(String clientId) {
+ return delegate.getConsentByClient(clientId);
}
@Override
- public List<GrantedConsentModel> getGrantedConsents() {
- return delegate.getGrantedConsents();
+ public List<UserConsentModel> getConsents() {
+ return delegate.getConsents();
}
@Override
- public void updateGrantedConsent(GrantedConsentModel consent) {
- delegate.updateGrantedConsent(consent);
+ public void updateConsent(UserConsentModel consent) {
+ delegate.updateConsent(consent);
}
@Override
- public boolean revokeGrantedConsentForClient(String clientId) {
- return delegate.revokeGrantedConsentForClient(clientId);
+ public boolean revokeConsentForClient(String clientId) {
+ return delegate.revokeConsentForClient(clientId);
}
}
diff --git a/model/file/src/main/java/org/keycloak/models/file/adapter/ClientAdapter.java b/model/file/src/main/java/org/keycloak/models/file/adapter/ClientAdapter.java
index 18cc9c8..34ddb06 100755
--- a/model/file/src/main/java/org/keycloak/models/file/adapter/ClientAdapter.java
+++ b/model/file/src/main/java/org/keycloak/models/file/adapter/ClientAdapter.java
@@ -277,7 +277,8 @@ public class ClientAdapter implements ClientModel {
throw new RuntimeException("protocol mapper name must be unique per protocol");
}
ProtocolMapperEntity entity = new ProtocolMapperEntity();
- entity.setId(KeycloakModelUtils.generateId());
+ String id = model.getId() != null ? model.getId() : KeycloakModelUtils.generateId();
+ entity.setId(id);
entity.setProtocol(model.getProtocol());
entity.setName(model.getName());
entity.setProtocolMapper(model.getProtocolMapper());
diff --git a/model/file/src/main/java/org/keycloak/models/file/adapter/UserAdapter.java b/model/file/src/main/java/org/keycloak/models/file/adapter/UserAdapter.java
index 3033eea..0937e2c 100755
--- a/model/file/src/main/java/org/keycloak/models/file/adapter/UserAdapter.java
+++ b/model/file/src/main/java/org/keycloak/models/file/adapter/UserAdapter.java
@@ -20,7 +20,7 @@ import org.keycloak.models.ClientModel;
import static org.keycloak.models.utils.Pbkdf2PasswordEncoder.getSalt;
-import org.keycloak.models.GrantedConsentModel;
+import org.keycloak.models.UserConsentModel;
import org.keycloak.models.PasswordPolicy;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
@@ -432,30 +432,29 @@ public class UserAdapter implements UserModel, Comparable {
}
@Override
- public GrantedConsentModel addGrantedConsent(GrantedConsentModel consent) {
+ public void addConsent(UserConsentModel consent) {
// TODO
- return null;
}
@Override
- public GrantedConsentModel getGrantedConsentByClient(String clientId) {
+ public UserConsentModel getConsentByClient(String clientId) {
// TODO
return null;
}
@Override
- public List<GrantedConsentModel> getGrantedConsents() {
+ public List<UserConsentModel> getConsents() {
// TODO
return null;
}
@Override
- public void updateGrantedConsent(GrantedConsentModel consent) {
+ public void updateConsent(UserConsentModel consent) {
// TODO
}
@Override
- public boolean revokeGrantedConsentForClient(String clientId) {
+ public boolean revokeConsentForClient(String clientId) {
// TODO
return false;
}
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/UserAdapter.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/UserAdapter.java
index 97b62fc..10336fd 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/UserAdapter.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/UserAdapter.java
@@ -1,7 +1,7 @@
package org.keycloak.models.cache;
import org.keycloak.models.ClientModel;
-import org.keycloak.models.GrantedConsentModel;
+import org.keycloak.models.UserConsentModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleContainerModel;
@@ -277,34 +277,34 @@ public class UserAdapter implements UserModel {
}
@Override
- public GrantedConsentModel addGrantedConsent(GrantedConsentModel consent) {
+ public void addConsent(UserConsentModel consent) {
getDelegateForUpdate();
- return updated.addGrantedConsent(consent);
+ updated.addConsent(consent);
}
@Override
- public GrantedConsentModel getGrantedConsentByClient(String clientId) {
+ public UserConsentModel getConsentByClient(String clientId) {
// TODO: caching?
getDelegateForUpdate();
- return updated.getGrantedConsentByClient(clientId);
+ return updated.getConsentByClient(clientId);
}
@Override
- public List<GrantedConsentModel> getGrantedConsents() {
+ public List<UserConsentModel> getConsents() {
// TODO: caching?
getDelegateForUpdate();
- return updated.getGrantedConsents();
+ return updated.getConsents();
}
@Override
- public void updateGrantedConsent(GrantedConsentModel consent) {
+ public void updateConsent(UserConsentModel consent) {
getDelegateForUpdate();
- updated.updateGrantedConsent(consent);
+ updated.updateConsent(consent);
}
@Override
- public boolean revokeGrantedConsentForClient(String clientId) {
+ public boolean revokeConsentForClient(String clientId) {
getDelegateForUpdate();
- return updated.revokeGrantedConsentForClient(clientId);
+ return updated.revokeConsentForClient(clientId);
}
}
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 498db9a..f9f62b6 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
@@ -378,7 +378,7 @@ public class ClientAdapter implements ClientModel {
if (getProtocolMapperByName(model.getProtocol(), model.getName()) != null) {
throw new RuntimeException("protocol mapper name must be unique per protocol");
}
- String id = KeycloakModelUtils.generateId();
+ String id = model.getId() != null ? model.getId() : KeycloakModelUtils.generateId();
ProtocolMapperEntity entity = new ProtocolMapperEntity();
entity.setId(id);
entity.setName(model.getName());
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 15300d0..d0af512 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
@@ -88,9 +88,9 @@ public class JpaUserProvider implements UserProvider {
private void removeUser(UserEntity user) {
em.createNamedQuery("deleteUserRoleMappingsByUser").setParameter("user", user).executeUpdate();
em.createNamedQuery("deleteFederatedIdentityByUser").setParameter("user", user).executeUpdate();
- em.createNamedQuery("deleteGrantedConsentRolesByUser").setParameter("user", user).executeUpdate();
- em.createNamedQuery("deleteGrantedConsentProtMappersByUser").setParameter("user", user).executeUpdate();
- em.createNamedQuery("deleteGrantedConsentsByUser").setParameter("user", user).executeUpdate();
+ em.createNamedQuery("deleteUserConsentRolesByUser").setParameter("user", user).executeUpdate();
+ em.createNamedQuery("deleteUserConsentProtMappersByUser").setParameter("user", user).executeUpdate();
+ em.createNamedQuery("deleteUserConsentsByUser").setParameter("user", user).executeUpdate();
em.remove(user);
}
@@ -134,11 +134,11 @@ public class JpaUserProvider implements UserProvider {
@Override
public void preRemove(RealmModel realm) {
- int num = em.createNamedQuery("deleteGrantedConsentRolesByRealm")
+ int num = em.createNamedQuery("deleteUserConsentRolesByRealm")
.setParameter("realmId", realm.getId()).executeUpdate();
- num = em.createNamedQuery("deleteGrantedConsentProtMappersByRealm")
+ num = em.createNamedQuery("deleteUserConsentProtMappersByRealm")
.setParameter("realmId", realm.getId()).executeUpdate();
- num = em.createNamedQuery("deleteGrantedConsentsByRealm")
+ num = em.createNamedQuery("deleteUserConsentsByRealm")
.setParameter("realmId", realm.getId()).executeUpdate();
num = em.createNamedQuery("deleteUserRoleMappingsByRealm")
.setParameter("realmId", realm.getId()).executeUpdate();
@@ -184,20 +184,20 @@ public class JpaUserProvider implements UserProvider {
@Override
public void preRemove(RealmModel realm, RoleModel role) {
- em.createNamedQuery("deleteGrantedConsentRolesByRole").setParameter("roleId", role.getId()).executeUpdate();
+ em.createNamedQuery("deleteUserConsentRolesByRole").setParameter("roleId", role.getId()).executeUpdate();
em.createNamedQuery("deleteUserRoleMappingsByRole").setParameter("roleId", role.getId()).executeUpdate();
}
@Override
public void preRemove(RealmModel realm, ClientModel client) {
- em.createNamedQuery("deleteGrantedConsentProtMappersByClient").setParameter("clientId", client.getId()).executeUpdate();
- em.createNamedQuery("deleteGrantedConsentRolesByClient").setParameter("clientId", client.getId()).executeUpdate();
- em.createNamedQuery("deleteGrantedConsentsByClient").setParameter("clientId", client.getId()).executeUpdate();
+ em.createNamedQuery("deleteUserConsentProtMappersByClient").setParameter("clientId", client.getId()).executeUpdate();
+ em.createNamedQuery("deleteUserConsentRolesByClient").setParameter("clientId", client.getId()).executeUpdate();
+ em.createNamedQuery("deleteUserConsentsByClient").setParameter("clientId", client.getId()).executeUpdate();
}
@Override
public void preRemove(ClientModel client, ProtocolMapperModel protocolMapper) {
- em.createNamedQuery("deleteGrantedConsentProtMappersByProtocolMapper")
+ em.createNamedQuery("deleteUserConsentProtMappersByProtocolMapper")
.setParameter("protocolMapperId", protocolMapper.getId())
.executeUpdate();
}
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/UserAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/UserAdapter.java
index f8d9352..737e0e3 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/UserAdapter.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/UserAdapter.java
@@ -1,7 +1,8 @@
package org.keycloak.models.jpa;
import org.keycloak.models.ClientModel;
-import org.keycloak.models.GrantedConsentModel;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.UserConsentModel;
import org.keycloak.models.ModelDuplicateException;
import org.keycloak.models.ModelException;
import org.keycloak.models.PasswordPolicy;
@@ -12,9 +13,9 @@ import org.keycloak.models.UserCredentialModel;
import org.keycloak.models.UserCredentialValueModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.jpa.entities.CredentialEntity;
-import org.keycloak.models.jpa.entities.GrantedConsentEntity;
-import org.keycloak.models.jpa.entities.GrantedConsentProtocolMapperEntity;
-import org.keycloak.models.jpa.entities.GrantedConsentRoleEntity;
+import org.keycloak.models.jpa.entities.UserConsentEntity;
+import org.keycloak.models.jpa.entities.UserConsentProtocolMapperEntity;
+import org.keycloak.models.jpa.entities.UserConsentRoleEntity;
import org.keycloak.models.jpa.entities.UserAttributeEntity;
import org.keycloak.models.jpa.entities.UserEntity;
import org.keycloak.models.jpa.entities.UserRequiredActionEntity;
@@ -29,7 +30,6 @@ import javax.persistence.TypedQuery;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
-import java.util.Date;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
@@ -480,18 +480,15 @@ public class UserAdapter implements UserModel {
}
@Override
- public GrantedConsentModel addGrantedConsent(GrantedConsentModel consent) {
- String clientId = consent.getClientId();
- if (clientId == null) {
- throw new ModelException("clientId needs to be filled for newly added consent!");
- }
+ public void addConsent(UserConsentModel consent) {
+ String clientId = consent.getClient().getId();
- GrantedConsentEntity consentEntity = getGrantedConsentEntity(clientId);
+ UserConsentEntity consentEntity = getGrantedConsentEntity(clientId);
if (consentEntity != null) {
throw new ModelDuplicateException("Consent already exists for client [" + clientId + "] and user [" + user.getId() + "]");
}
- consentEntity = new GrantedConsentEntity();
+ consentEntity = new UserConsentEntity();
consentEntity.setId(KeycloakModelUtils.generateId());
consentEntity.setUser(user);
consentEntity.setClientId(clientId);
@@ -499,38 +496,33 @@ public class UserAdapter implements UserModel {
em.flush();
updateGrantedConsentEntity(consentEntity, consent);
-
- return consent;
}
@Override
- public GrantedConsentModel getGrantedConsentByClient(String clientId) {
- GrantedConsentEntity entity = getGrantedConsentEntity(clientId);
+ public UserConsentModel getConsentByClient(String clientId) {
+ UserConsentEntity entity = getGrantedConsentEntity(clientId);
return toConsentModel(entity);
}
@Override
- public List<GrantedConsentModel> getGrantedConsents() {
- TypedQuery<GrantedConsentEntity> query = em.createNamedQuery("grantedConsentsByUser", GrantedConsentEntity.class);
+ public List<UserConsentModel> getConsents() {
+ TypedQuery<UserConsentEntity> query = em.createNamedQuery("userConsentsByUser", UserConsentEntity.class);
query.setParameter("userId", getId());
- List<GrantedConsentEntity> results = query.getResultList();
+ List<UserConsentEntity> results = query.getResultList();
- List<GrantedConsentModel> consents = new ArrayList<GrantedConsentModel>();
- for (GrantedConsentEntity entity : results) {
- GrantedConsentModel model = toConsentModel(entity);
+ List<UserConsentModel> consents = new ArrayList<UserConsentModel>();
+ for (UserConsentEntity entity : results) {
+ UserConsentModel model = toConsentModel(entity);
consents.add(model);
}
return consents;
}
@Override
- public void updateGrantedConsent(GrantedConsentModel consent) {
- String clientId = consent.getClientId();
- if (clientId == null) {
- throw new ModelException("clientId needs to be for newly added consent!");
- }
+ public void updateConsent(UserConsentModel consent) {
+ String clientId = consent.getClient().getId();
- GrantedConsentEntity consentEntity = getGrantedConsentEntity(clientId);
+ UserConsentEntity consentEntity = getGrantedConsentEntity(clientId);
if (consentEntity == null) {
throw new ModelException("Consent not found for client [" + clientId + "] and user [" + user.getId() + "]");
}
@@ -539,8 +531,8 @@ public class UserAdapter implements UserModel {
}
@Override
- public boolean revokeGrantedConsentForClient(String clientId) {
- GrantedConsentEntity consentEntity = getGrantedConsentEntity(clientId);
+ public boolean revokeConsentForClient(String clientId) {
+ UserConsentEntity consentEntity = getGrantedConsentEntity(clientId);
if (consentEntity == null) return false;
em.remove(consentEntity);
@@ -549,11 +541,11 @@ public class UserAdapter implements UserModel {
}
- private GrantedConsentEntity getGrantedConsentEntity(String clientId) {
- TypedQuery<GrantedConsentEntity> query = em.createNamedQuery("grantedConsentByUserAndClient", GrantedConsentEntity.class);
+ private UserConsentEntity getGrantedConsentEntity(String clientId) {
+ TypedQuery<UserConsentEntity> query = em.createNamedQuery("userConsentByUserAndClient", UserConsentEntity.class);
query.setParameter("userId", getId());
query.setParameter("clientId", clientId);
- List<GrantedConsentEntity> results = query.getResultList();
+ List<UserConsentEntity> results = query.getResultList();
if (results.size() > 1) {
throw new ModelException("More results found for user [" + getUsername() + "] and client [" + clientId + "]");
} else if (results.size() == 1) {
@@ -563,23 +555,23 @@ public class UserAdapter implements UserModel {
}
}
- private GrantedConsentModel toConsentModel(GrantedConsentEntity entity) {
+ private UserConsentModel toConsentModel(UserConsentEntity entity) {
if (entity == null) {
return null;
}
- GrantedConsentModel model = new GrantedConsentModel(entity.getClientId());
+ UserConsentModel model = new UserConsentModel(realm, entity.getClientId());
- Collection<GrantedConsentRoleEntity> grantedRoleEntities = entity.getGrantedRoles();
+ Collection<UserConsentRoleEntity> grantedRoleEntities = entity.getGrantedRoles();
if (grantedRoleEntities != null) {
- for (GrantedConsentRoleEntity grantedRole : grantedRoleEntities) {
+ for (UserConsentRoleEntity grantedRole : grantedRoleEntities) {
model.addGrantedRole(grantedRole.getRoleId());
}
}
- Collection<GrantedConsentProtocolMapperEntity> grantedProtocolMapperEntities = entity.getGrantedProtocolMappers();
+ Collection<UserConsentProtocolMapperEntity> grantedProtocolMapperEntities = entity.getGrantedProtocolMappers();
if (grantedProtocolMapperEntities != null) {
- for (GrantedConsentProtocolMapperEntity grantedProtMapper : grantedProtocolMapperEntities) {
+ for (UserConsentProtocolMapperEntity grantedProtMapper : grantedProtocolMapperEntities) {
model.addGrantedProtocolMapper(grantedProtMapper.getProtocolMapperId());
}
}
@@ -588,14 +580,14 @@ public class UserAdapter implements UserModel {
}
// Update roles and protocolMappers to given consentEntity from the consentModel
- private void updateGrantedConsentEntity(GrantedConsentEntity consentEntity, GrantedConsentModel consentModel) {
- Collection<GrantedConsentProtocolMapperEntity> grantedProtocolMapperEntities = consentEntity.getGrantedProtocolMappers();
- Collection<GrantedConsentProtocolMapperEntity> mappersToRemove = new HashSet<GrantedConsentProtocolMapperEntity>(grantedProtocolMapperEntities);
+ private void updateGrantedConsentEntity(UserConsentEntity consentEntity, UserConsentModel consentModel) {
+ Collection<UserConsentProtocolMapperEntity> grantedProtocolMapperEntities = consentEntity.getGrantedProtocolMappers();
+ Collection<UserConsentProtocolMapperEntity> mappersToRemove = new HashSet<UserConsentProtocolMapperEntity>(grantedProtocolMapperEntities);
- for (String protocolMapperId : consentModel.getGrantedProtocolMappers()) {
- GrantedConsentProtocolMapperEntity grantedProtocolMapperEntity = new GrantedConsentProtocolMapperEntity();
- grantedProtocolMapperEntity.setGrantedConsent(consentEntity);
- grantedProtocolMapperEntity.setProtocolMapperId(protocolMapperId);
+ for (ProtocolMapperModel protocolMapper : consentModel.getGrantedProtocolMappers()) {
+ UserConsentProtocolMapperEntity grantedProtocolMapperEntity = new UserConsentProtocolMapperEntity();
+ grantedProtocolMapperEntity.setUserConsent(consentEntity);
+ grantedProtocolMapperEntity.setProtocolMapperId(protocolMapper.getId());
// Check if it's already there
if (!grantedProtocolMapperEntities.contains(grantedProtocolMapperEntity)) {
@@ -607,17 +599,17 @@ public class UserAdapter implements UserModel {
}
}
// Those mappers were no longer on consentModel and will be removed
- for (GrantedConsentProtocolMapperEntity toRemove : mappersToRemove) {
+ for (UserConsentProtocolMapperEntity toRemove : mappersToRemove) {
grantedProtocolMapperEntities.remove(toRemove);
em.remove(toRemove);
}
- Collection<GrantedConsentRoleEntity> grantedRoleEntities = consentEntity.getGrantedRoles();
- Set<GrantedConsentRoleEntity> rolesToRemove = new HashSet<GrantedConsentRoleEntity>(grantedRoleEntities);
- for (String roleId : consentModel.getGrantedRoles()) {
- GrantedConsentRoleEntity consentRoleEntity = new GrantedConsentRoleEntity();
- consentRoleEntity.setGrantedConsent(consentEntity);
- consentRoleEntity.setRoleId(roleId);
+ Collection<UserConsentRoleEntity> grantedRoleEntities = consentEntity.getGrantedRoles();
+ Set<UserConsentRoleEntity> rolesToRemove = new HashSet<UserConsentRoleEntity>(grantedRoleEntities);
+ for (RoleModel role : consentModel.getGrantedRoles()) {
+ UserConsentRoleEntity consentRoleEntity = new UserConsentRoleEntity();
+ consentRoleEntity.setUserConsent(consentEntity);
+ consentRoleEntity.setRoleId(role.getId());
// Check if it's already there
if (!grantedRoleEntities.contains(consentRoleEntity)) {
@@ -629,7 +621,7 @@ public class UserAdapter implements UserModel {
}
}
// Those roles were no longer on consentModel and will be removed
- for (GrantedConsentRoleEntity toRemove : rolesToRemove) {
+ for (UserConsentRoleEntity toRemove : rolesToRemove) {
grantedRoleEntities.remove(toRemove);
em.remove(toRemove);
}
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 8e07bc9..2cb2c79 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
@@ -305,7 +305,8 @@ public class ClientAdapter extends AbstractMongoAdapter<MongoClientEntity> imple
throw new RuntimeException("protocol mapper name must be unique per protocol");
}
ProtocolMapperEntity entity = new ProtocolMapperEntity();
- entity.setId(KeycloakModelUtils.generateId());
+ String id = model.getId() != null ? model.getId() : KeycloakModelUtils.generateId();
+ entity.setId(id);
entity.setProtocol(model.getProtocol());
entity.setName(model.getName());
entity.setProtocolMapper(model.getProtocolMapper());
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoUserProvider.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoUserProvider.java
index f71c797..83bc85c 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoUserProvider.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoUserProvider.java
@@ -17,6 +17,7 @@ import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserProvider;
import org.keycloak.models.entities.FederatedIdentityEntity;
+import org.keycloak.models.mongo.keycloak.entities.MongoUserConsentEntity;
import org.keycloak.models.mongo.keycloak.entities.MongoUserEntity;
import org.keycloak.models.utils.CredentialValidation;
@@ -43,7 +44,6 @@ public class MongoUserProvider implements UserProvider {
@Override
public void close() {
- // TODO
}
@Override
@@ -274,11 +274,7 @@ public class MongoUserProvider implements UserProvider {
@Override
public boolean removeUser(RealmModel realm, UserModel user) {
- DBObject query = new QueryBuilder()
- .and("_id").is(user.getId())
- .and("realmId").is(realm.getId())
- .get();
- return getMongoStore().removeEntities(MongoUserEntity.class, query, invocationContext);
+ return getMongoStore().removeEntity(MongoUserEntity.class, user.getId(), invocationContext);
}
@@ -339,32 +335,60 @@ public class MongoUserProvider implements UserProvider {
DBObject query = new QueryBuilder()
.and("realmId").is(realm.getId())
.get();
- getMongoStore().removeEntities(MongoUserEntity.class, query, invocationContext);
+ getMongoStore().removeEntities(MongoUserEntity.class, query, true, invocationContext);
}
@Override
public void preRemove(RealmModel realm, UserFederationProviderModel link) {
+ // Remove all users linked with federationProvider and their consents
DBObject query = new QueryBuilder()
.and("realmId").is(realm.getId())
.and("federationLink").is(link.getId())
.get();
- getMongoStore().removeEntities(MongoUserEntity.class, query, invocationContext);
+ getMongoStore().removeEntities(MongoUserEntity.class, query, true, invocationContext);
}
@Override
public void preRemove(RealmModel realm, ClientModel client) {
- // TODO
+ // Remove all role mappings and consents mapped to all roles of this client
+ for (RoleModel role : client.getRoles()) {
+ preRemove(realm, role);
+ }
+
+ // Finally remove all consents of this client
+ DBObject query = new QueryBuilder()
+ .and("clientId").is(client.getId())
+ .get();
+ getMongoStore().removeEntities(MongoUserConsentEntity.class, query, false, invocationContext);
}
@Override
public void preRemove(ClientModel client, ProtocolMapperModel protocolMapper) {
- // TODO
+ // Remove this protocol mapper from all consents, which has it
+ DBObject query = new QueryBuilder()
+ .and("grantedProtocolMappers").is(protocolMapper.getId())
+ .get();
+ DBObject pull = new BasicDBObject("$pull", query);
+ getMongoStore().updateEntities(MongoUserEntity.class, query, pull, invocationContext);
}
@Override
public void preRemove(RealmModel realm, RoleModel role) {
- // todo not sure what to do for this
+ // Remove this role from all users, which has it
+ DBObject query = new QueryBuilder()
+ .and("roleIds").is(role.getId())
+ .get();
+
+ DBObject pull = new BasicDBObject("$pull", query);
+ getMongoStore().updateEntities(MongoUserEntity.class, query, pull, invocationContext);
+
+ // Remove this role from all consents, which has it
+ query = new QueryBuilder()
+ .and("grantedRoles").is(role.getId())
+ .get();
+ pull = new BasicDBObject("$pull", query);
+ getMongoStore().updateEntities(MongoUserConsentEntity.class, query, pull, invocationContext);
}
@Override
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/UserAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/UserAdapter.java
index 5fa3e52..b054793 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/UserAdapter.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/UserAdapter.java
@@ -2,10 +2,15 @@ package org.keycloak.models.mongo.keycloak.adapters;
import static org.keycloak.models.utils.Pbkdf2PasswordEncoder.getSalt;
+import com.mongodb.DBObject;
+import com.mongodb.QueryBuilder;
import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
import org.keycloak.models.ClientModel;
-import org.keycloak.models.GrantedConsentModel;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.UserConsentModel;
import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ModelDuplicateException;
+import org.keycloak.models.ModelException;
import org.keycloak.models.PasswordPolicy;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
@@ -13,7 +18,9 @@ import org.keycloak.models.UserCredentialModel;
import org.keycloak.models.UserCredentialValueModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.entities.CredentialEntity;
+import org.keycloak.models.entities.UserConsentEntity;
import org.keycloak.models.mongo.keycloak.entities.MongoRoleEntity;
+import org.keycloak.models.mongo.keycloak.entities.MongoUserConsentEntity;
import org.keycloak.models.mongo.keycloak.entities.MongoUserEntity;
import org.keycloak.models.mongo.utils.MongoModelUtils;
import org.keycloak.models.utils.Pbkdf2PasswordEncoder;
@@ -22,9 +29,9 @@ import org.keycloak.util.Time;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
-import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -360,30 +367,18 @@ public class UserAdapter extends AbstractMongoAdapter<MongoUserEntity> implement
@Override
public Set<RoleModel> getRoleMappings() {
- Set<RoleModel> result = new HashSet<RoleModel>();
- List<MongoRoleEntity> roles = MongoModelUtils.getAllRolesOfUser(this, invocationContext);
-
- for (MongoRoleEntity role : roles) {
- if (realm.getId().equals(role.getRealmId())) {
- result.add(new RoleAdapter(session, realm, role, realm, invocationContext));
- } else {
- // Likely applicationRole, but we don't have this application yet
- result.add(new RoleAdapter(session, realm, role, invocationContext));
- }
- }
- return result;
+ List<RoleModel> roles = MongoModelUtils.getAllRolesOfUser(realm, this);
+ return new HashSet<RoleModel>(roles);
}
@Override
public Set<RoleModel> getRealmRoleMappings() {
Set<RoleModel> allRoles = getRoleMappings();
- // Filter to retrieve just realm roles TODO: Maybe improve to avoid filter programmatically... Maybe have separate fields for realmRoles and appRoles on user?
+ // Filter to retrieve just realm roles
Set<RoleModel> realmRoles = new HashSet<RoleModel>();
for (RoleModel role : allRoles) {
- MongoRoleEntity roleEntity = ((RoleAdapter) role).getRole();
-
- if (realm.getId().equals(roleEntity.getRealmId())) {
+ if (role.getContainer() instanceof RealmModel) {
realmRoles.add(role);
}
}
@@ -400,11 +395,11 @@ public class UserAdapter extends AbstractMongoAdapter<MongoUserEntity> implement
@Override
public Set<RoleModel> getClientRoleMappings(ClientModel app) {
Set<RoleModel> result = new HashSet<RoleModel>();
- List<MongoRoleEntity> roles = MongoModelUtils.getAllRolesOfUser(this, invocationContext);
+ List<RoleModel> roles = MongoModelUtils.getAllRolesOfUser(realm, this);
- for (MongoRoleEntity role : roles) {
- if (app.getId().equals(role.getClientId())) {
- result.add(new RoleAdapter(session, realm, role, app, invocationContext));
+ for (RoleModel role : roles) {
+ if (app.equals(role.getContainer())) {
+ result.add(role);
}
}
return result;
@@ -422,32 +417,96 @@ public class UserAdapter extends AbstractMongoAdapter<MongoUserEntity> implement
}
@Override
- public GrantedConsentModel addGrantedConsent(GrantedConsentModel consent) {
- // TODO
- return null;
+ public void addConsent(UserConsentModel consent) {
+ String clientId = consent.getClient().getId();
+ if (getConsentEntityByClientId(clientId) != null) {
+ throw new ModelDuplicateException("Consent already exists for client [" + clientId + "] and user [" + user.getId() + "]");
+ }
+
+ MongoUserConsentEntity consentEntity = new MongoUserConsentEntity();
+ consentEntity.setUserId(getId());
+ consentEntity.setClientId(clientId);
+ fillEntityFromModel(consent, consentEntity);
+ getMongoStore().insertEntity(consentEntity, invocationContext);
}
@Override
- public GrantedConsentModel getGrantedConsentByClient(String clientId) {
- // TODO
- return null;
+ public UserConsentModel getConsentByClient(String clientId) {
+ UserConsentEntity consentEntity = getConsentEntityByClientId(clientId);
+ return consentEntity!=null ? toConsentModel(consentEntity) : null;
}
@Override
- public List<GrantedConsentModel> getGrantedConsents() {
- // TODO
- return null;
+ public List<UserConsentModel> getConsents() {
+ List<UserConsentModel> result = new ArrayList<UserConsentModel>();
+
+ DBObject query = new QueryBuilder()
+ .and("userId").is(getId())
+ .get();
+ List<MongoUserConsentEntity> grantedConsents = getMongoStore().loadEntities(MongoUserConsentEntity.class, query, invocationContext);
+
+ for (UserConsentEntity consentEntity : grantedConsents) {
+ UserConsentModel model = toConsentModel(consentEntity);
+ result.add(model);
+ }
+
+ return result;
+ }
+
+ private MongoUserConsentEntity getConsentEntityByClientId(String clientId) {
+ DBObject query = new QueryBuilder()
+ .and("userId").is(getId())
+ .and("clientId").is(clientId)
+ .get();
+ return getMongoStore().loadSingleEntity(MongoUserConsentEntity.class, query, invocationContext);
+ }
+
+ private UserConsentModel toConsentModel(UserConsentEntity entity) {
+ UserConsentModel model = new UserConsentModel(realm, entity.getClientId());
+ for (String roleId : entity.getGrantedRoles()) {
+ model.addGrantedRole(roleId);
+ }
+ for (String protMapperId : entity.getGrantedProtocolMappers()) {
+ model.addGrantedProtocolMapper(protMapperId);
+ }
+ return model;
+ }
+
+ // Fill roles and protocolMappers to entity
+ private void fillEntityFromModel(UserConsentModel consent, MongoUserConsentEntity consentEntity) {
+ List<String> roleIds = new LinkedList<String>();
+ for (RoleModel role : consent.getGrantedRoles()) {
+ roleIds.add(role.getId());
+ }
+ consentEntity.setGrantedRoles(roleIds);
+
+ List<String> protMapperIds = new LinkedList<String>();
+ for (ProtocolMapperModel protMapperModel : consent.getGrantedProtocolMappers()) {
+ protMapperIds.add(protMapperModel.getId());
+ }
+ consentEntity.setGrantedProtocolMappers(protMapperIds);
}
@Override
- public void updateGrantedConsent(GrantedConsentModel consent) {
- // TODO
+ public void updateConsent(UserConsentModel consent) {
+ String clientId = consent.getClient().getId();
+ MongoUserConsentEntity consentEntity = getConsentEntityByClientId(clientId);
+ if (consentEntity == null) {
+ throw new ModelException("Consent not found for client [" + clientId + "] and user [" + user.getId() + "]");
+ } else {
+ fillEntityFromModel(consent, consentEntity);
+ getMongoStore().updateEntity(consentEntity, invocationContext);
+ }
}
@Override
- public boolean revokeGrantedConsentForClient(String clientId) {
- // TODO
- return false;
+ public boolean revokeConsentForClient(String clientId) {
+ MongoUserConsentEntity entity = getConsentEntityByClientId(clientId);
+ if (entity == null) {
+ return false;
+ }
+
+ return getMongoStore().removeEntity(entity, invocationContext);
}
@Override
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoClientEntity.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoClientEntity.java
index cc97d5d..8c12715 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoClientEntity.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoClientEntity.java
@@ -19,6 +19,6 @@ public class MongoClientEntity extends ClientEntity implements MongoIdentifiable
DBObject query = new QueryBuilder()
.and("clientId").is(getId())
.get();
- context.getMongoStore().removeEntities(MongoRoleEntity.class, query, context);
+ context.getMongoStore().removeEntities(MongoRoleEntity.class, query, true, context);
}
}
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoRealmEntity.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoRealmEntity.java
index 2209751..a64c2b5 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoRealmEntity.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoRealmEntity.java
@@ -19,13 +19,10 @@ public class MongoRealmEntity extends RealmEntity implements MongoIdentifiableEn
.and("realmId").is(getId())
.get();
- // Remove all users of this realm
- context.getMongoStore().removeEntities(MongoUserEntity.class, query, context);
-
// Remove all roles of this realm
- context.getMongoStore().removeEntities(MongoRoleEntity.class, query, context);
+ context.getMongoStore().removeEntities(MongoRoleEntity.class, query, true, context);
- // Remove all applications of this realm
- context.getMongoStore().removeEntities(MongoClientEntity.class, query, context);
+ // Remove all clients of this realm
+ context.getMongoStore().removeEntities(MongoClientEntity.class, query, true, context);
}
}
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoRoleEntity.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoRoleEntity.java
index dc820c2..2021069 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoRoleEntity.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoRoleEntity.java
@@ -41,26 +41,15 @@ public class MongoRoleEntity extends RoleEntity implements MongoIdentifiableEnti
public void afterRemove(MongoStoreInvocationContext invContext) {
MongoStore mongoStore = invContext.getMongoStore();
- // Remove this role from all users, which has it
+ // Remove this scope from all clients, which has it
DBObject query = new QueryBuilder()
- .and("roleIds").is(getId())
- .get();
-
- List<MongoUserEntity> users = mongoStore.loadEntities(MongoUserEntity.class, query, invContext);
- for (MongoUserEntity user : users) {
- //logger.info("Removing role " + getName() + " from user " + user.getUsername());
- mongoStore.pullItemFromList(user, "roleIds", getId(), invContext);
- }
-
- // Remove this scope from all users, which has it
- query = new QueryBuilder()
.and("scopeIds").is(getId())
.get();
- users = mongoStore.loadEntities(MongoUserEntity.class, query, invContext);
- for (MongoUserEntity user : users) {
+ List<MongoClientEntity> clients = mongoStore.loadEntities(MongoClientEntity.class, query, invContext);
+ for (MongoClientEntity client : clients) {
//logger.info("Removing scope " + getName() + " from user " + user.getUsername());
- mongoStore.pullItemFromList(user, "scopeIds", getId(), invContext);
+ mongoStore.pullItemFromList(client, "scopeIds", getId(), invContext);
}
// Remove defaultRoles from realm
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoUserConsentEntity.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoUserConsentEntity.java
new file mode 100644
index 0000000..16e0026
--- /dev/null
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoUserConsentEntity.java
@@ -0,0 +1,17 @@
+package org.keycloak.models.mongo.keycloak.entities;
+
+import org.keycloak.connections.mongo.api.MongoCollection;
+import org.keycloak.connections.mongo.api.MongoIdentifiableEntity;
+import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
+import org.keycloak.models.entities.UserConsentEntity;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+@MongoCollection(collectionName = "userConsents")
+public class MongoUserConsentEntity extends UserConsentEntity implements MongoIdentifiableEntity {
+
+ @Override
+ public void afterRemove(MongoStoreInvocationContext invocationContext) {
+ }
+}
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoUserEntity.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoUserEntity.java
index c9f317e..d1700d8 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoUserEntity.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoUserEntity.java
@@ -1,5 +1,7 @@
package org.keycloak.models.mongo.keycloak.entities;
+import com.mongodb.DBObject;
+import com.mongodb.QueryBuilder;
import org.keycloak.connections.mongo.api.MongoCollection;
import org.keycloak.connections.mongo.api.MongoIdentifiableEntity;
import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
@@ -19,6 +21,12 @@ public class MongoUserEntity extends UserEntity implements MongoIdentifiableEnti
}
@Override
- public void afterRemove(MongoStoreInvocationContext invocationContext) {
+ public void afterRemove(MongoStoreInvocationContext context) {
+ // Remove all consents of this user
+ DBObject query = new QueryBuilder()
+ .and("userId").is(getId())
+ .get();
+
+ context.getMongoStore().removeEntities(MongoUserConsentEntity.class, query, true, context);
}
}
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/utils/MongoModelUtils.java b/model/mongo/src/main/java/org/keycloak/models/mongo/utils/MongoModelUtils.java
index 48828de..02923cf 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/utils/MongoModelUtils.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/utils/MongoModelUtils.java
@@ -4,6 +4,8 @@ import com.mongodb.DBObject;
import com.mongodb.QueryBuilder;
import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
import org.keycloak.models.ClientModel;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.entities.ClientEntity;
import org.keycloak.models.mongo.keycloak.adapters.ClientAdapter;
@@ -12,6 +14,7 @@ import org.keycloak.models.mongo.keycloak.entities.MongoRoleEntity;
import org.keycloak.models.mongo.keycloak.entities.MongoUserEntity;
import java.util.Collections;
+import java.util.LinkedList;
import java.util.List;
/**
@@ -20,18 +23,22 @@ import java.util.List;
public class MongoModelUtils {
// Get everything including both application and realm roles
- public static List<MongoRoleEntity> getAllRolesOfUser(UserModel user, MongoStoreInvocationContext invContext) {
+ public static List<RoleModel> getAllRolesOfUser(RealmModel realm, UserModel user) {
MongoUserEntity userEntity = ((UserAdapter)user).getUser();
List<String> roleIds = userEntity.getRoleIds();
if (roleIds == null || roleIds.isEmpty()) {
- return Collections.EMPTY_LIST;
+ return Collections.emptyList();
}
- DBObject query = new QueryBuilder()
- .and("_id").in(roleIds)
- .get();
- return invContext.getMongoStore().loadEntities(MongoRoleEntity.class, query, invContext);
+ List<RoleModel> roles = new LinkedList<RoleModel>();
+ for (String roleId : roleIds) {
+ RoleModel role = realm.getRoleById(roleId);
+ if (role != null) {
+ roles.add(role);
+ }
+ }
+ return roles;
}
// Get everything including both application and realm scopes
@@ -40,7 +47,7 @@ public class MongoModelUtils {
List<String> scopeIds = scopedEntity.getScopeIds();
if (scopeIds == null || scopeIds.isEmpty()) {
- return Collections.EMPTY_LIST;
+ return Collections.emptyList();
}
DBObject query = new QueryBuilder()
diff --git a/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/entities/MongoUserSessionEntity.java b/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/entities/MongoUserSessionEntity.java
index 5b7e8d3..0c637db 100755
--- a/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/entities/MongoUserSessionEntity.java
+++ b/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/entities/MongoUserSessionEntity.java
@@ -121,7 +121,7 @@ public class MongoUserSessionEntity extends AbstractIdentifiableEntity implement
DBObject query = new QueryBuilder()
.and("sessionId").is(getId())
.get();
- context.getMongoStore().removeEntities(MongoClientSessionEntity.class, query, context);
+ context.getMongoStore().removeEntities(MongoClientSessionEntity.class, query, true, context);
}
public Map<String, String> getNotes() {
diff --git a/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/MongoUserSessionProvider.java b/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/MongoUserSessionProvider.java
index 0bc5849..848fdeb 100755
--- a/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/MongoUserSessionProvider.java
+++ b/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/MongoUserSessionProvider.java
@@ -194,18 +194,14 @@ public class MongoUserSessionProvider implements UserSessionProvider {
@Override
public void removeUserSessions(RealmModel realm, UserModel user) {
DBObject query = new BasicDBObject("user", user.getId());
- mongoStore.removeEntities(MongoUserSessionEntity.class, query, invocationContext);
+ mongoStore.removeEntities(MongoUserSessionEntity.class, query, true, invocationContext);
}
@Override
public void removeUserSessions(RealmModel realm) {
DBObject query = new BasicDBObject("realmId", realm.getId());
- mongoStore.removeEntities(MongoUserSessionEntity.class, query, invocationContext);
- query = new QueryBuilder()
- .and("realmId").is(realm.getId())
- .get();
-
- mongoStore.removeEntities(MongoClientSessionEntity.class, query, invocationContext);
+ mongoStore.removeEntities(MongoUserSessionEntity.class, query, false, invocationContext);
+ mongoStore.removeEntities(MongoClientSessionEntity.class, query, false, invocationContext);
}
@Override
@@ -216,20 +212,20 @@ public class MongoUserSessionProvider implements UserSessionProvider {
.and("started").lessThan(currentTime - realm.getSsoSessionMaxLifespan())
.get();
- mongoStore.removeEntities(MongoUserSessionEntity.class, query, invocationContext);
+ mongoStore.removeEntities(MongoUserSessionEntity.class, query, true, invocationContext);
query = new QueryBuilder()
.and("realmId").is(realm.getId())
.and("lastSessionRefresh").lessThan(currentTime - realm.getSsoSessionIdleTimeout())
.get();
- mongoStore.removeEntities(MongoUserSessionEntity.class, query, invocationContext);
+ mongoStore.removeEntities(MongoUserSessionEntity.class, query, true, invocationContext);
query = new QueryBuilder()
.and("sessionId").is(null)
.and("realmId").is(realm.getId())
.and("timestamp").lessThan(currentTime - RealmInfoUtil.getDettachedClientSessionLifespan(realm))
.get();
- mongoStore.removeEntities(MongoClientSessionEntity.class, query, invocationContext);
+ mongoStore.removeEntities(MongoClientSessionEntity.class, query, false, invocationContext);
}
@Override
@@ -291,7 +287,7 @@ public class MongoUserSessionProvider implements UserSessionProvider {
.or(new BasicDBObject("username", user.getUsername()), new BasicDBObject("username", user.getEmail()))
.and("realmId").is(realm.getId())
.get();
- mongoStore.removeEntities(MongoUsernameLoginFailureEntity.class, query, invocationContext);
+ mongoStore.removeEntities(MongoUsernameLoginFailureEntity.class, query, true, invocationContext);
}
@Override
diff --git a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
index 4814f30..7647b36 100755
--- a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
@@ -14,7 +14,7 @@ import org.keycloak.jose.jws.JWSBuilder;
import org.keycloak.login.LoginFormsProvider;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.GrantedConsentModel;
+import org.keycloak.models.UserConsentModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.RealmModel;
@@ -420,14 +420,14 @@ public class AuthenticationManager {
if (client.isConsentRequired()) {
accessCode.setAction(ClientSessionModel.Action.OAUTH_GRANT);
- GrantedConsentModel grantedConsent = user.getGrantedConsentByClient(client.getId());
+ UserConsentModel grantedConsent = user.getConsentByClient(client.getId());
List<RoleModel> realmRoles = new LinkedList<RoleModel>();
MultivaluedMap<String, RoleModel> resourceRoles = new MultivaluedMapImpl<String, RoleModel>();
for (RoleModel r : accessCode.getRequestedRoles()) {
// Consent already granted by user
- if (grantedConsent != null && grantedConsent.getGrantedRoles().contains(r.getId())) {
+ if (grantedConsent != null && grantedConsent.isRoleGranted(r)) {
continue;
}
@@ -439,10 +439,10 @@ public class AuthenticationManager {
}
List<ProtocolMapperModel> protocolMappers = new LinkedList<ProtocolMapperModel>();
- for (ProtocolMapperModel model : client.getProtocolMappers()) {
- if (model.isConsentRequired() && model.getProtocol().equals(clientSession.getAuthMethod()) && model.getConsentText() != null) {
- if (grantedConsent == null || !grantedConsent.getGrantedProtocolMappers().contains(model.getId())) {
- protocolMappers.add(model);
+ for (ProtocolMapperModel protocolMapper : client.getProtocolMappers()) {
+ if (protocolMapper.isConsentRequired() && protocolMapper.getProtocol().equals(clientSession.getAuthMethod()) && protocolMapper.getConsentText() != null) {
+ if (grantedConsent == null || !grantedConsent.isProtocolMapperGranted(protocolMapper)) {
+ protocolMappers.add(protocolMapper);
}
}
}
diff --git a/services/src/main/java/org/keycloak/services/resources/AccountService.java b/services/src/main/java/org/keycloak/services/resources/AccountService.java
index af1c872..3a775e1 100755
--- a/services/src/main/java/org/keycloak/services/resources/AccountService.java
+++ b/services/src/main/java/org/keycloak/services/resources/AccountService.java
@@ -76,7 +76,6 @@ import javax.ws.rs.core.Variant;
import java.lang.reflect.Method;
import java.net.URI;
-import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
@@ -512,7 +511,7 @@ public class AccountService {
// Revoke grant in UserModel
UserModel user = auth.getUser();
- user.revokeGrantedConsentForClient(client.getId());
+ user.revokeConsentForClient(client.getId());
// Logout clientSessions for this user and client
List<UserSessionModel> userSessions = session.sessions().getUserSessions(realm, user);
diff --git a/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java b/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java
index a0eb4dc..d4aa8d7 100755
--- a/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java
+++ b/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java
@@ -34,7 +34,7 @@ import org.keycloak.jose.jws.JWSBuilder;
import org.keycloak.login.LoginFormsProvider;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.GrantedConsentModel;
+import org.keycloak.models.UserConsentModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ModelException;
import org.keycloak.models.ProtocolMapperModel;
@@ -609,9 +609,10 @@ public class LoginActionsService {
return protocol.consentDenied(clientSession);
}
- GrantedConsentModel grantedConsent = user.getGrantedConsentByClient(client.getId());
+ UserConsentModel grantedConsent = user.getConsentByClient(client.getId());
if (grantedConsent == null) {
- grantedConsent = user.addGrantedConsent(new GrantedConsentModel(client.getId()));
+ grantedConsent = new UserConsentModel(realm, client.getId());
+ user.addConsent(grantedConsent);
}
for (String roleId : clientSession.getRoles()) {
grantedConsent.addGrantedRole(roleId);
@@ -622,7 +623,7 @@ public class LoginActionsService {
grantedConsent.addGrantedProtocolMapper(protocolMapper.getId());
}
}
- user.updateGrantedConsent(grantedConsent);
+ user.updateConsent(grantedConsent);
event.success();
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/AdapterTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/AdapterTest.java
index 0e48914..f7f48b3 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/AdapterTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/AdapterTest.java
@@ -258,6 +258,7 @@ public class AdapterTest extends AbstractModelTest {
commit();
realmModel = model.getRealm("JUGGLER");
app = realmModel.getClientByClientId("test-app");
+ user = realmManager.getSession().users().getUserByUsername("bburke", realmModel);
Assert.assertTrue(realmModel.removeRoleById(realmRole.getId()));
Assert.assertFalse(realmModel.removeRoleById(realmRole.getId()));
@@ -266,6 +267,9 @@ public class AdapterTest extends AbstractModelTest {
Assert.assertTrue(realmModel.removeRoleById(appRole.getId()));
Assert.assertFalse(realmModel.removeRoleById(appRole.getId()));
assertNull(app.getRole(appRole.getName()));
+
+ user = realmManager.getSession().users().getUserByUsername("bburke", realmModel);
+
}
@Test
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ClientModelTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ClientModelTest.java
index f0fc63b..e56d462 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ClientModelTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ClientModelTest.java
@@ -9,6 +9,7 @@ import org.keycloak.models.RoleModel;
import org.keycloak.models.utils.ModelToRepresentation;
import org.keycloak.models.utils.RepresentationToModel;
import org.keycloak.representations.idm.ClientRepresentation;
+import org.keycloak.representations.idm.ProtocolMapperRepresentation;
import org.keycloak.services.managers.ClientManager;
import java.util.Iterator;
@@ -63,6 +64,9 @@ public class ClientModelTest extends AbstractModelTest {
public void json() {
ClientRepresentation representation = ModelToRepresentation.toRepresentation(client);
representation.setId(null);
+ for (ProtocolMapperRepresentation protocolMapper : representation.getProtocolMappers()) {
+ protocolMapper.setId(null);
+ }
RealmModel realm = realmManager.createRealm("copy");
ClientModel copy = RepresentationToModel.createClient(session, realm, representation, true);
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ImportTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ImportTest.java
index 54f4cbe..5bdc191 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ImportTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ImportTest.java
@@ -14,6 +14,7 @@ import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RequiredCredentialModel;
import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserConsentModel;
import org.keycloak.models.UserFederationProvider;
import org.keycloak.models.UserFederationProviderFactory;
import org.keycloak.models.UserFederationProviderModel;
@@ -238,6 +239,23 @@ public class ImportTest extends AbstractModelTest {
String includeInIdToken = gssCredentialMapper.getConfig().get(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN);
Assert.assertTrue(includeInAccessToken.equalsIgnoreCase("true"));
Assert.assertTrue(includeInIdToken == null || Boolean.parseBoolean(includeInIdToken) == false);
+
+ // Test user consents
+ admin = session.users().getUserByUsername("admin", realm);
+ Assert.assertEquals(2, admin.getConsents().size());
+
+ UserConsentModel appAdminConsent = admin.getConsentByClient(application.getId());
+ Assert.assertEquals(2, appAdminConsent.getGrantedRoles().size());
+ Assert.assertTrue(appAdminConsent.getGrantedProtocolMappers() == null || appAdminConsent.getGrantedProtocolMappers().isEmpty());
+ Assert.assertTrue(appAdminConsent.isRoleGranted(realm.getRole("admin")));
+ Assert.assertTrue(appAdminConsent.isRoleGranted(application.getRole("app-admin")));
+
+ UserConsentModel otherAppAdminConsent = admin.getConsentByClient(otherApp.getId());
+ Assert.assertEquals(1, otherAppAdminConsent.getGrantedRoles().size());
+ Assert.assertEquals(1, otherAppAdminConsent.getGrantedProtocolMappers().size());
+ Assert.assertTrue(otherAppAdminConsent.isRoleGranted(realm.getRole("admin")));
+ Assert.assertFalse(otherAppAdminConsent.isRoleGranted(application.getRole("app-admin")));
+ Assert.assertTrue(otherAppAdminConsent.isProtocolMapperGranted(gssCredentialMapper));
}
@Test
diff --git a/testsuite/integration/src/test/resources/model/testrealm.json b/testsuite/integration/src/test/resources/model/testrealm.json
index 4044399..1c0b7e6 100755
--- a/testsuite/integration/src/test/resources/model/testrealm.json
+++ b/testsuite/integration/src/test/resources/model/testrealm.json
@@ -74,6 +74,15 @@
"applicationRoles": {
"Application": [ "app-admin" ],
"OtherApp": [ "otherapp-admin" ]
+ },
+ "clientConsents": {
+ "Application": {
+ "grantedRoles": [ "456", "789" ]
+ },
+ "OtherApp": {
+ "grantedProtocolMappers": [ "123" ],
+ "grantedRoles": [ "456" ]
+ }
}
},
{
@@ -113,6 +122,7 @@
"enabled": true,
"protocolMappers" : [
{
+ "id": "123",
"name" : "gss delegation credential",
"protocol" : "openid-connect",
"protocolMapper" : "oidc-usersessionmodel-note-mapper",
@@ -138,12 +148,14 @@
"roles" : {
"realm" : [
{
+ "id": "456",
"name": "admin"
}
],
"application" : {
"Application" : [
{
+ "id": "789",
"name": "app-admin"
},
{