Skip to content

Commit

Permalink
KEYCLOAK-1070 Rename GrantedConsentModel to UserConsentModel. Mongo s…
Browse files Browse the repository at this point in the history
…upport for consents. Mongo fixes
  • Loading branch information
mposolda committed Apr 22, 2015
1 parent 136fd37 commit 11035db
Show file tree
Hide file tree
Showing 39 changed files with 866 additions and 642 deletions.
Expand Up @@ -35,7 +35,7 @@
<addColumn tableName="CREDENTIAL"> <addColumn tableName="CREDENTIAL">
<column name="CREATED_DATE" type="BIGINT"/> <column name="CREATED_DATE" type="BIGINT"/>
</addColumn> </addColumn>
<createTable tableName="GRANTED_CONSENT"> <createTable tableName="USER_CONSENT">
<column name="ID" type="VARCHAR(36)"> <column name="ID" type="VARCHAR(36)">
<constraints nullable="false"/> <constraints nullable="false"/>
</column> </column>
Expand All @@ -46,16 +46,16 @@
<constraints nullable="false"/> <constraints nullable="false"/>
</column> </column>
</createTable> </createTable>
<createTable tableName="GRANTED_CONSENT_ROLE"> <createTable tableName="USER_CONSENT_ROLE">
<column name="GRANTED_CONSENT_ID" type="VARCHAR(36)"> <column name="USER_CONSENT_ID" type="VARCHAR(36)">
<constraints nullable="false"/> <constraints nullable="false"/>
</column> </column>
<column name="ROLE_ID" type="VARCHAR(36)"> <column name="ROLE_ID" type="VARCHAR(36)">
<constraints nullable="false"/> <constraints nullable="false"/>
</column> </column>
</createTable> </createTable>
<createTable tableName="GRANTED_CONSENT_PROT_MAPPER"> <createTable tableName="USER_CONSENT_PROT_MAPPER">
<column name="GRANTED_CONSENT_ID" type="VARCHAR(36)"> <column name="USER_CONSENT_ID" type="VARCHAR(36)">
<constraints nullable="false"/> <constraints nullable="false"/>
</column> </column>
<column name="PROTOCOL_MAPPER_ID" type="VARCHAR(36)"> <column name="PROTOCOL_MAPPER_ID" type="VARCHAR(36)">
Expand All @@ -64,14 +64,14 @@
</createTable> </createTable>
<addPrimaryKey columnNames="ID" constraintName="CONSTRAINT_IDPM" tableName="IDENTITY_PROVIDER_MAPPER"/> <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="IDP_MAPPER_ID, NAME" constraintName="CONSTRAINT_IDPMConfig" tableName="IDP_MAPPER_CONFIG"/>
<addPrimaryKey columnNames="ID" constraintName="CONSTRAINT_GRNTCSNT_PM" tableName="GRANTED_CONSENT"/> <addPrimaryKey columnNames="ID" constraintName="CONSTRAINT_GRNTCSNT_PM" tableName="USER_CONSENT"/>
<addPrimaryKey columnNames="GRANTED_CONSENT_ID, ROLE_ID" constraintName="CONSTRAINT_GRNTCSNT_ROLE_PM" tableName="GRANTED_CONSENT_ROLE"/> <addPrimaryKey columnNames="USER_CONSENT_ID, ROLE_ID" constraintName="CONSTRAINT_GRNTCSNT_ROLE_PM" tableName="USER_CONSENT_ROLE"/>
<addPrimaryKey columnNames="GRANTED_CONSENT_ID, PROTOCOL_MAPPER_ID" constraintName="CONSTRAINT_GRNTCSNT_PRM_PM" tableName="GRANTED_CONSENT_PROT_MAPPER"/> <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="REALM_ID" baseTableName="IDENTITY_PROVIDER_MAPPER" constraintName="FK_IDPM_REALM" referencedColumnNames="ID" referencedTableName="REALM"/>
<addForeignKeyConstraint baseColumnNames="IDP_MAPPER_ID" baseTableName="IDP_MAPPER_CONFIG" constraintName="FK_IDPMConfig" referencedColumnNames="ID" referencedTableName="IDENTITY_PROVIDER_MAPPER"/> <addForeignKeyConstraint baseColumnNames="IDP_MAPPER_ID" baseTableName="IDP_MAPPER_CONFIG" constraintName="FK_IDPMConfig" referencedColumnNames="ID" referencedTableName="IDENTITY_PROVIDER_MAPPER"/>
<addForeignKeyConstraint baseColumnNames="USER_ID" baseTableName="GRANTED_CONSENT" constraintName="FK_GRNTCSNT_USER" referencedColumnNames="ID" referencedTableName="USER_ENTITY"/> <addForeignKeyConstraint baseColumnNames="USER_ID" baseTableName="USER_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="USER_CONSENT_ID" baseTableName="USER_CONSENT_ROLE" constraintName="FK_GRNTCSNT_ROLE_GR" referencedColumnNames="ID" referencedTableName="USER_CONSENT"/>
<addForeignKeyConstraint baseColumnNames="GRANTED_CONSENT_ID" baseTableName="GRANTED_CONSENT_PROT_MAPPER" constraintName="FK_GRNTCSNT_PRM_GR" referencedColumnNames="ID" referencedTableName="GRANTED_CONSENT"/> <addForeignKeyConstraint baseColumnNames="USER_CONSENT_ID" baseTableName="USER_CONSENT_PROT_MAPPER" constraintName="FK_GRNTCSNT_PRM_GR" referencedColumnNames="ID" referencedTableName="USER_CONSENT"/>


<addColumn tableName="CLIENT"> <addColumn tableName="CLIENT">
<column name="CONSENT_REQUIRED" type="BOOLEAN" defaultValueBoolean="false"> <column name="CONSENT_REQUIRED" type="BOOLEAN" defaultValueBoolean="false">
Expand Down Expand Up @@ -101,7 +101,7 @@


<dropUniqueConstraint tableName="KEYCLOAK_ROLE" constraintName="UK_J3RWUVD56ONTGSUHOGM184WW2"/> <dropUniqueConstraint tableName="KEYCLOAK_ROLE" constraintName="UK_J3RWUVD56ONTGSUHOGM184WW2"/>
<addUniqueConstraint columnNames="NAME,CLIENT_REALM_CONSTRAINT" constraintName="UK_J3RWUVD56ONTGSUHOGM184WW2-2" tableName="KEYCLOAK_ROLE"/> <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> </changeSet>
</databaseChangeLog> </databaseChangeLog>
6 changes: 3 additions & 3 deletions connections/jpa/src/main/resources/META-INF/persistence.xml
Expand Up @@ -20,9 +20,9 @@
<class>org.keycloak.models.jpa.entities.IdentityProviderMapperEntity</class> <class>org.keycloak.models.jpa.entities.IdentityProviderMapperEntity</class>
<class>org.keycloak.models.jpa.entities.ClientIdentityProviderMappingEntity</class> <class>org.keycloak.models.jpa.entities.ClientIdentityProviderMappingEntity</class>
<class>org.keycloak.models.jpa.entities.ProtocolMapperEntity</class> <class>org.keycloak.models.jpa.entities.ProtocolMapperEntity</class>
<class>org.keycloak.models.jpa.entities.GrantedConsentEntity</class> <class>org.keycloak.models.jpa.entities.UserConsentEntity</class>
<class>org.keycloak.models.jpa.entities.GrantedConsentRoleEntity</class> <class>org.keycloak.models.jpa.entities.UserConsentRoleEntity</class>
<class>org.keycloak.models.jpa.entities.GrantedConsentProtocolMapperEntity</class> <class>org.keycloak.models.jpa.entities.UserConsentProtocolMapperEntity</class>


<!-- JpaUserSessionProvider --> <!-- JpaUserSessionProvider -->
<class>org.keycloak.models.sessions.jpa.entities.ClientSessionEntity</class> <class>org.keycloak.models.sessions.jpa.entities.ClientSessionEntity</class>
Expand Down
Expand Up @@ -22,6 +22,7 @@ public void update(KeycloakSession session) {


db.getCollection("realms").update(new BasicDBObject(), new BasicDBObject("$rename", new BasicDBObject("adminAppId", "clientId")), false, true); 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() { private void convertApplicationsToClients() {
Expand Down
Expand Up @@ -38,7 +38,8 @@ public class DefaultMongoConnectionFactoryProvider implements MongoConnectionPro
"org.keycloak.models.sessions.mongo.entities.MongoUserSessionEntity", "org.keycloak.models.sessions.mongo.entities.MongoUserSessionEntity",
"org.keycloak.models.sessions.mongo.entities.MongoClientSessionEntity", "org.keycloak.models.sessions.mongo.entities.MongoClientSessionEntity",
"org.keycloak.models.entities.UserFederationProviderEntity", "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); private static final Logger logger = Logger.getLogger(DefaultMongoConnectionFactoryProvider.class);
Expand Down
Expand Up @@ -24,13 +24,35 @@ public interface MongoStore {
*/ */
void updateEntity(MongoIdentifiableEntity entity, MongoStoreInvocationContext context); 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 loadEntity(Class<T> type, String id, MongoStoreInvocationContext context);


<T extends MongoIdentifiableEntity> T loadSingleEntity(Class<T> type, DBObject query, 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); <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> 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); <T extends MongoIdentifiableEntity> int countEntities(Class<T> type, DBObject query, MongoStoreInvocationContext context);
Expand All @@ -39,7 +61,16 @@ public interface MongoStore {


boolean removeEntity(Class<? extends MongoIdentifiableEntity> type, String id, MongoStoreInvocationContext context); 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); <S> boolean pushItemToList(MongoIdentifiableEntity entity, String listPropertyName, S itemToPush, boolean skipIfAlreadyPresent, MongoStoreInvocationContext context);


Expand Down
Expand Up @@ -22,6 +22,8 @@ public interface MongoStoreInvocationContext {


void beforeDBSearch(Class<? extends MongoIdentifiableEntity> entityType); void beforeDBSearch(Class<? extends MongoIdentifiableEntity> entityType);


void beforeDBBulkUpdateOrRemove(Class<? extends MongoIdentifiableEntity> entityType);

void begin(); void begin();


void commit(); void commit();
Expand Down
Expand Up @@ -7,6 +7,7 @@
import com.mongodb.DBCursor; import com.mongodb.DBCursor;
import com.mongodb.DBObject; import com.mongodb.DBObject;
import com.mongodb.MongoException; import com.mongodb.MongoException;
import com.mongodb.WriteResult;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
import org.keycloak.connections.mongo.api.MongoCollection; import org.keycloak.connections.mongo.api.MongoCollection;
import org.keycloak.connections.mongo.api.MongoEntity; import org.keycloak.connections.mongo.api.MongoEntity;
Expand Down Expand Up @@ -127,7 +128,7 @@ public void insertEntity(MongoIdentifiableEntity entity, MongoStoreInvocationCon
throw convertException(e); 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); context.addCreatedEntity(entity);
} }


Expand Down Expand Up @@ -170,6 +171,16 @@ public boolean isFullUpdate() {
context.addUpdateTask(entity, fullUpdateTask); 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 @Override
public <T extends MongoIdentifiableEntity> T loadEntity(Class<T> type, String id, MongoStoreInvocationContext context) { public <T extends MongoIdentifiableEntity> T loadEntity(Class<T> type, String id, MongoStoreInvocationContext context) {
Expand Down Expand Up @@ -275,19 +286,32 @@ public boolean removeEntity(Class<? extends MongoIdentifiableEntity> type, Strin




@Override @Override
public boolean removeEntities(Class<? extends MongoIdentifiableEntity> type, DBObject query, MongoStoreInvocationContext context) { public int removeEntities(Class<? extends MongoIdentifiableEntity> type, DBObject query, boolean callback, MongoStoreInvocationContext context) {
List<? extends MongoIdentifiableEntity> foundObjects = loadEntities(type, query, context); if (callback) {
if (foundObjects.size() == 0) { List<? extends MongoIdentifiableEntity> foundObjects = loadEntities(type, query, context);
return false; 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 { } else {

context.beforeDBBulkUpdateOrRemove(type);

DBCollection dbCollection = getDBCollectionForType(type); DBCollection dbCollection = getDBCollectionForType(type);
dbCollection.remove(query); WriteResult writeResult = dbCollection.remove(query);
//logger.debug("Removed %d" + foundObjects.size() + " entities of type: " + type + ", query: " + query); int removedCount = writeResult.getN();


for (MongoIdentifiableEntity found : foundObjects) { logger.debugf("Removed directly %d entities of type: %s, query: %s", removedCount, type, query);
context.addRemovedEntity(found);; return removedCount;
}
return true;
} }
} }


Expand Down
Expand Up @@ -45,6 +45,10 @@ public void addRemovedEntity(MongoIdentifiableEntity entity) {
public void beforeDBSearch(Class<? extends MongoIdentifiableEntity> entityType) { public void beforeDBSearch(Class<? extends MongoIdentifiableEntity> entityType) {
} }


@Override
public void beforeDBBulkUpdateOrRemove(Class<? extends MongoIdentifiableEntity> entityType) {
}

@Override @Override
public void begin() { public void begin() {
} }
Expand Down
Expand Up @@ -50,10 +50,6 @@ public <T extends MongoIdentifiableEntity> T getLoadedEntity(Class<T> type, Stri


@Override @Override
public void addUpdateTask(MongoIdentifiableEntity entityToUpdate, MongoTask task) { 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); Set<MongoTask> currentObjectTasks = pendingUpdateTasks.get(entityToUpdate);
if (currentObjectTasks == null) { if (currentObjectTasks == null) {
currentObjectTasks = new LinkedHashSet<MongoTask>(); currentObjectTasks = new LinkedHashSet<MongoTask>();
Expand Down Expand Up @@ -106,6 +102,24 @@ public void beforeDBSearch(Class<? extends MongoIdentifiableEntity> entityType)
} }
} }


@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 @Override
public void begin() { public void begin() {
loadedObjects.clear(); loadedObjects.clear();
Expand Down
Expand Up @@ -5,7 +5,7 @@
import java.util.List; import java.util.List;


import org.keycloak.models.ClientModel; import org.keycloak.models.ClientModel;
import org.keycloak.models.GrantedConsentModel; import org.keycloak.models.UserConsentModel;
import org.keycloak.models.ProtocolMapperModel; import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.RealmModel; import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel; import org.keycloak.models.RoleModel;
Expand All @@ -20,14 +20,13 @@ public class AccessBean {
private List<ClientGrantBean> clientGrants = new LinkedList<ClientGrantBean>(); private List<ClientGrantBean> clientGrants = new LinkedList<ClientGrantBean>();


public AccessBean(RealmModel realm, UserModel user, URI baseUri, String stateChecker) { public AccessBean(RealmModel realm, UserModel user, URI baseUri, String stateChecker) {
List<GrantedConsentModel> grantedConsents = user.getGrantedConsents(); List<UserConsentModel> grantedConsents = user.getGrantedConsents();
for (GrantedConsentModel consent : grantedConsents) { for (UserConsentModel consent : grantedConsents) {
ClientModel client = realm.getClientById(consent.getClientId()); ClientModel client = consent.getClient();


List<RoleModel> realmRolesGranted = new LinkedList<RoleModel>(); List<RoleModel> realmRolesGranted = new LinkedList<RoleModel>();
MultivaluedHashMap<String, RoleModel> resourceRolesGranted = new MultivaluedHashMap<String, RoleModel>(); MultivaluedHashMap<String, RoleModel> resourceRolesGranted = new MultivaluedHashMap<String, RoleModel>();
for (String roleId : consent.getGrantedRoles()) { for (RoleModel role : consent.getGrantedRoles()) {
RoleModel role = realm.getRoleById(roleId);
if (role.getContainer() instanceof RealmModel) { if (role.getContainer() instanceof RealmModel) {
realmRolesGranted.add(role); realmRolesGranted.add(role);
} else { } else {
Expand All @@ -36,8 +35,7 @@ public AccessBean(RealmModel realm, UserModel user, URI baseUri, String stateChe
} }


List<String> claimsGranted = new LinkedList<String>(); List<String> claimsGranted = new LinkedList<String>();
for (String protocolMapperId : consent.getGrantedProtocolMappers()) { for (ProtocolMapperModel protocolMapper : consent.getGrantedProtocolMappers()) {
ProtocolMapperModel protocolMapper = client.getProtocolMapperById(protocolMapperId);
claimsGranted.add(protocolMapper.getConsentText()); claimsGranted.add(protocolMapper.getConsentText());
} }


Expand Down

This file was deleted.

0 comments on commit 11035db

Please sign in to comment.