From 4f00f6cceb5e230b7fd218456e930df52d037188 Mon Sep 17 00:00:00 2001 From: Bill Burke Date: Wed, 18 Nov 2015 15:24:27 -0500 Subject: [PATCH] group mongo --- ...DefaultMongoConnectionFactoryProvider.java | 1 + .../keycloak/models/jpa/JpaUserProvider.java | 1 + .../org/keycloak/models/jpa/RealmAdapter.java | 1 + .../mongo/keycloak/adapters/GroupAdapter.java | 30 ++++++++++--- .../mongo/keycloak/adapters/RealmAdapter.java | 4 +- .../keycloak/entities/MongoRealmEntity.java | 4 ++ .../keycloak/entities/MongoRoleEntity.java | 12 +++++ .../exportimport/ExportImportTest.java | 5 ++- .../resources/keycloak-saml/testsaml.json | 44 +++++++++++++++++++ .../resources/keycloak-saml/testsaml.json | 44 +++++++++++++++++++ .../resources/keycloak-saml/testsaml.json | 44 +++++++++++++++++++ .../resources/keycloak-saml/testsaml.json | 44 +++++++++++++++++++ .../resources/keycloak-saml/testsaml.json | 44 +++++++++++++++++++ .../resources/keycloak-saml/testsaml.json | 44 +++++++++++++++++++ 14 files changed, 311 insertions(+), 11 deletions(-) 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 ae9701b475..67cb127a90 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 @@ -35,6 +35,7 @@ public class DefaultMongoConnectionFactoryProvider implements MongoConnectionPro "org.keycloak.models.mongo.keycloak.entities.MongoRealmEntity", "org.keycloak.models.mongo.keycloak.entities.MongoUserEntity", "org.keycloak.models.mongo.keycloak.entities.MongoRoleEntity", + "org.keycloak.models.mongo.keycloak.entities.MongoGroupEntity", "org.keycloak.models.mongo.keycloak.entities.MongoClientEntity", "org.keycloak.models.mongo.keycloak.entities.MongoUserConsentEntity", "org.keycloak.models.mongo.keycloak.entities.MongoMigrationModelEntity", 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 dcee81d9c7..61e4982e88 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 @@ -97,6 +97,7 @@ public class JpaUserProvider implements UserProvider { private void removeUser(UserEntity user) { String id = user.getId(); em.createNamedQuery("deleteUserRoleMappingsByUser").setParameter("user", user).executeUpdate(); + em.createNamedQuery("deleteUserGroupMembershipsByUser").setParameter("user", user).executeUpdate(); em.createNamedQuery("deleteFederatedIdentityByUser").setParameter("user", user).executeUpdate(); em.createNamedQuery("deleteUserConsentRolesByUser").setParameter("user", user).executeUpdate(); em.createNamedQuery("deleteUserConsentProtMappersByUser").setParameter("user", user).executeUpdate(); diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java index ef6c32bc8e..eae002b545 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java @@ -1000,6 +1000,7 @@ public class RealmAdapter implements RealmModel { String compositeRoleTable = JpaUtils.getTableNameForNativeQuery("COMPOSITE_ROLE", em); em.createNativeQuery("delete from " + compositeRoleTable + " where CHILD_ROLE = :role").setParameter("role", roleEntity).executeUpdate(); em.createNamedQuery("deleteScopeMappingByRole").setParameter("role", roleEntity).executeUpdate(); + em.createNamedQuery("deleteGroupRoleMappingsByRole").setParameter("roleId", roleEntity.getId()).executeUpdate(); em.remove(roleEntity); diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/GroupAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/GroupAdapter.java index d261c6daa0..180eb9d399 100755 --- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/GroupAdapter.java +++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/GroupAdapter.java @@ -6,6 +6,7 @@ import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext; import org.keycloak.models.ClientModel; import org.keycloak.models.GroupModel; import org.keycloak.models.KeycloakSession; +import org.keycloak.models.ModelException; import org.keycloak.models.RealmModel; import org.keycloak.models.RoleContainerModel; import org.keycloak.models.RoleModel; @@ -20,6 +21,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; @@ -146,7 +148,11 @@ public class GroupAdapter extends AbstractMongoAdapter impleme if (group.getRoleIds() == null || group.getRoleIds().isEmpty()) return Collections.EMPTY_SET; Set roles = new HashSet<>(); for (String id : group.getRoleIds()) { - roles.add(realm.getRoleById(id)); + RoleModel roleById = realm.getRoleById(id); + if (roleById == null) { + throw new ModelException("role does not exist in group role mappings"); + } + roles.add(roleById); } return roles; } @@ -198,18 +204,28 @@ public class GroupAdapter extends AbstractMongoAdapter impleme @Override public Set getSubGroups() { + DBObject query = new QueryBuilder() + .and("realmId").is(realm.getId()) + .and("parentId").is(getId()) + .get(); + List groups = getMongoStore().loadEntities(MongoGroupEntity.class, query, invocationContext); + Set subGroups = new HashSet<>(); - for (GroupModel groupModel : realm.getGroups()) { - if (groupModel.getParent().equals(this)) { - subGroups.add(groupModel); - } + + if (groups == null) return subGroups; + for (MongoGroupEntity group : groups) { + subGroups.add(realm.getGroupById(group.getId())); } + return subGroups; } @Override - public void setParent(GroupModel group) { - this.group.setParentId(group.getId()); + public void setParent(GroupModel parent) { + if (parent == null) group.setParentId(null); + else { + group.setParentId(parent.getId()); + } updateGroup(); } diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java index cab0ddf17f..2fe85a11a9 100755 --- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java +++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java @@ -660,7 +660,7 @@ public class RealmAdapter extends AbstractMongoAdapter impleme if (groups == null) return result; for (MongoGroupEntity group : groups) { - result.add(new GroupAdapter(session, this, group, invocationContext)); + result.add(model.getGroupById(group.getId(), this)); } return result; @@ -672,7 +672,7 @@ public class RealmAdapter extends AbstractMongoAdapter impleme Iterator it = all.iterator(); while (it.hasNext()) { GroupModel group = it.next(); - if (group.getParent() != null) { + if (group.getParentId() != null) { it.remove(); } } 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 8269360085..78f107692c 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,6 +19,10 @@ public class MongoRealmEntity extends RealmEntity implements MongoIdentifiableEn .and("realmId").is(getId()) .get(); + // Remove all roles of this realm + context.getMongoStore().removeEntities(MongoGroupEntity.class, query, true, context); + + // Remove all roles of this realm context.getMongoStore().removeEntities(MongoRoleEntity.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 29491f8533..520f678bf3 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,6 +41,18 @@ public class MongoRoleEntity extends RoleEntity implements MongoIdentifiableEnti public void afterRemove(MongoStoreInvocationContext invContext) { MongoStore mongoStore = invContext.getMongoStore(); + { + DBObject query = new QueryBuilder() + .and("roleIds").is(getId()) + .get(); + + List groups = mongoStore.loadEntities(MongoGroupEntity.class, query, invContext); + for (MongoGroupEntity group : groups) { + mongoStore.pullItemFromList(group, "roleIds", getId(), invContext); + } + + } + // Remove this scope from all clients, which has it DBObject query = new QueryBuilder() .and("scopeIds").is(getId()) diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/exportimport/ExportImportTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/exportimport/ExportImportTest.java index 1fc4fc22a0..2f89194d35 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/exportimport/ExportImportTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/exportimport/ExportImportTest.java @@ -163,8 +163,9 @@ public class ExportImportTest { testRealmExportImport(); - // There should be 3 files in target directory (1 realm, 2 user, 1 version) - Assert.assertEquals(4, new File(targetDirPath).listFiles().length); + // There should be 3 files in target directory (1 realm, 3 user, 1 version) + File[] files = new File(targetDirPath).listFiles(); + Assert.assertEquals(5, files.length); } @Test diff --git a/testsuite/jetty/jetty81/src/test/resources/keycloak-saml/testsaml.json b/testsuite/jetty/jetty81/src/test/resources/keycloak-saml/testsaml.json index 0b13fb9e9e..04c5dcdf0f 100755 --- a/testsuite/jetty/jetty81/src/test/resources/keycloak-saml/testsaml.json +++ b/testsuite/jetty/jetty81/src/test/resources/keycloak-saml/testsaml.json @@ -40,6 +40,30 @@ { "type" : "password", "value" : "password" } ] + }, + { + "username" : "topGroupUser", + "enabled": true, + "email" : "top@redhat.com", + "credentials" : [ + { "type" : "password", + "value" : "password" } + ], + "groups": [ + "/top" + ] + }, + { + "username" : "level2GroupUser", + "enabled": true, + "email" : "level2@redhat.com", + "credentials" : [ + { "type" : "password", + "value" : "password" } + ], + "groups": [ + "/top/level2" + ] } ], "applications": [ @@ -347,6 +371,26 @@ } } ], + "groups" : [ + { + "name": "top", + "attributes": { + "topAttribute": ["true"] + + }, + "realmRoles": ["manager"], + "subGroups": [ + { + "name": "level2", + "realmRoles": ["user"], + "attributes": { + "level2Attribute": ["true"] + + } + } + ] + } + ], "roles" : { "realm" : [ { diff --git a/testsuite/jetty/jetty91/src/test/resources/keycloak-saml/testsaml.json b/testsuite/jetty/jetty91/src/test/resources/keycloak-saml/testsaml.json index 0b13fb9e9e..04c5dcdf0f 100755 --- a/testsuite/jetty/jetty91/src/test/resources/keycloak-saml/testsaml.json +++ b/testsuite/jetty/jetty91/src/test/resources/keycloak-saml/testsaml.json @@ -40,6 +40,30 @@ { "type" : "password", "value" : "password" } ] + }, + { + "username" : "topGroupUser", + "enabled": true, + "email" : "top@redhat.com", + "credentials" : [ + { "type" : "password", + "value" : "password" } + ], + "groups": [ + "/top" + ] + }, + { + "username" : "level2GroupUser", + "enabled": true, + "email" : "level2@redhat.com", + "credentials" : [ + { "type" : "password", + "value" : "password" } + ], + "groups": [ + "/top/level2" + ] } ], "applications": [ @@ -347,6 +371,26 @@ } } ], + "groups" : [ + { + "name": "top", + "attributes": { + "topAttribute": ["true"] + + }, + "realmRoles": ["manager"], + "subGroups": [ + { + "name": "level2", + "realmRoles": ["user"], + "attributes": { + "level2Attribute": ["true"] + + } + } + ] + } + ], "roles" : { "realm" : [ { diff --git a/testsuite/jetty/jetty92/src/test/resources/keycloak-saml/testsaml.json b/testsuite/jetty/jetty92/src/test/resources/keycloak-saml/testsaml.json index 0b13fb9e9e..04c5dcdf0f 100755 --- a/testsuite/jetty/jetty92/src/test/resources/keycloak-saml/testsaml.json +++ b/testsuite/jetty/jetty92/src/test/resources/keycloak-saml/testsaml.json @@ -40,6 +40,30 @@ { "type" : "password", "value" : "password" } ] + }, + { + "username" : "topGroupUser", + "enabled": true, + "email" : "top@redhat.com", + "credentials" : [ + { "type" : "password", + "value" : "password" } + ], + "groups": [ + "/top" + ] + }, + { + "username" : "level2GroupUser", + "enabled": true, + "email" : "level2@redhat.com", + "credentials" : [ + { "type" : "password", + "value" : "password" } + ], + "groups": [ + "/top/level2" + ] } ], "applications": [ @@ -347,6 +371,26 @@ } } ], + "groups" : [ + { + "name": "top", + "attributes": { + "topAttribute": ["true"] + + }, + "realmRoles": ["manager"], + "subGroups": [ + { + "name": "level2", + "realmRoles": ["user"], + "attributes": { + "level2Attribute": ["true"] + + } + } + ] + } + ], "roles" : { "realm" : [ { diff --git a/testsuite/tomcat6/src/test/resources/keycloak-saml/testsaml.json b/testsuite/tomcat6/src/test/resources/keycloak-saml/testsaml.json index 0b13fb9e9e..04c5dcdf0f 100755 --- a/testsuite/tomcat6/src/test/resources/keycloak-saml/testsaml.json +++ b/testsuite/tomcat6/src/test/resources/keycloak-saml/testsaml.json @@ -40,6 +40,30 @@ { "type" : "password", "value" : "password" } ] + }, + { + "username" : "topGroupUser", + "enabled": true, + "email" : "top@redhat.com", + "credentials" : [ + { "type" : "password", + "value" : "password" } + ], + "groups": [ + "/top" + ] + }, + { + "username" : "level2GroupUser", + "enabled": true, + "email" : "level2@redhat.com", + "credentials" : [ + { "type" : "password", + "value" : "password" } + ], + "groups": [ + "/top/level2" + ] } ], "applications": [ @@ -347,6 +371,26 @@ } } ], + "groups" : [ + { + "name": "top", + "attributes": { + "topAttribute": ["true"] + + }, + "realmRoles": ["manager"], + "subGroups": [ + { + "name": "level2", + "realmRoles": ["user"], + "attributes": { + "level2Attribute": ["true"] + + } + } + ] + } + ], "roles" : { "realm" : [ { diff --git a/testsuite/tomcat7/src/test/resources/keycloak-saml/testsaml.json b/testsuite/tomcat7/src/test/resources/keycloak-saml/testsaml.json index 0b13fb9e9e..04c5dcdf0f 100755 --- a/testsuite/tomcat7/src/test/resources/keycloak-saml/testsaml.json +++ b/testsuite/tomcat7/src/test/resources/keycloak-saml/testsaml.json @@ -40,6 +40,30 @@ { "type" : "password", "value" : "password" } ] + }, + { + "username" : "topGroupUser", + "enabled": true, + "email" : "top@redhat.com", + "credentials" : [ + { "type" : "password", + "value" : "password" } + ], + "groups": [ + "/top" + ] + }, + { + "username" : "level2GroupUser", + "enabled": true, + "email" : "level2@redhat.com", + "credentials" : [ + { "type" : "password", + "value" : "password" } + ], + "groups": [ + "/top/level2" + ] } ], "applications": [ @@ -347,6 +371,26 @@ } } ], + "groups" : [ + { + "name": "top", + "attributes": { + "topAttribute": ["true"] + + }, + "realmRoles": ["manager"], + "subGroups": [ + { + "name": "level2", + "realmRoles": ["user"], + "attributes": { + "level2Attribute": ["true"] + + } + } + ] + } + ], "roles" : { "realm" : [ { diff --git a/testsuite/tomcat8/src/test/resources/keycloak-saml/testsaml.json b/testsuite/tomcat8/src/test/resources/keycloak-saml/testsaml.json index 0b13fb9e9e..04c5dcdf0f 100755 --- a/testsuite/tomcat8/src/test/resources/keycloak-saml/testsaml.json +++ b/testsuite/tomcat8/src/test/resources/keycloak-saml/testsaml.json @@ -40,6 +40,30 @@ { "type" : "password", "value" : "password" } ] + }, + { + "username" : "topGroupUser", + "enabled": true, + "email" : "top@redhat.com", + "credentials" : [ + { "type" : "password", + "value" : "password" } + ], + "groups": [ + "/top" + ] + }, + { + "username" : "level2GroupUser", + "enabled": true, + "email" : "level2@redhat.com", + "credentials" : [ + { "type" : "password", + "value" : "password" } + ], + "groups": [ + "/top/level2" + ] } ], "applications": [ @@ -347,6 +371,26 @@ } } ], + "groups" : [ + { + "name": "top", + "attributes": { + "topAttribute": ["true"] + + }, + "realmRoles": ["manager"], + "subGroups": [ + { + "name": "level2", + "realmRoles": ["user"], + "attributes": { + "level2Attribute": ["true"] + + } + } + ] + } + ], "roles" : { "realm" : [ {