keycloak-uncached

Merge pull request #1781 from mposolda/1.6.x KEYCLOAK-2005

10/26/2015 11:12:55 AM

Details

diff --git a/model/api/src/main/java/org/keycloak/migration/migrators/MigrateTo1_6_0.java b/model/api/src/main/java/org/keycloak/migration/migrators/MigrateTo1_6_0.java
index 88817ac..45c73a3 100644
--- a/model/api/src/main/java/org/keycloak/migration/migrators/MigrateTo1_6_0.java
+++ b/model/api/src/main/java/org/keycloak/migration/migrators/MigrateTo1_6_0.java
@@ -63,10 +63,8 @@ public class MigrateTo1_6_0 {
                 KeycloakModelUtils.setupOfflineTokens(realm);
                 RoleModel role = realm.getRole(Constants.OFFLINE_ACCESS_ROLE);
 
-                // Check if possible to avoid iterating over users
-                for (UserModel user : session.userStorage().getUsers(realm, true)) {
-                    user.grantRole(role);
-                }
+                // Bulk grant of offline_access role to all users
+                session.users().grantToAllUsers(realm, role);
             }
 
             ClientModel adminConsoleClient = realm.getClientByClientId(Constants.ADMIN_CONSOLE_CLIENT_ID);
diff --git a/model/api/src/main/java/org/keycloak/models/UserFederationManager.java b/model/api/src/main/java/org/keycloak/models/UserFederationManager.java
index bea51e0..cde5eb9 100755
--- a/model/api/src/main/java/org/keycloak/models/UserFederationManager.java
+++ b/model/api/src/main/java/org/keycloak/models/UserFederationManager.java
@@ -334,6 +334,12 @@ public class UserFederationManager implements UserProvider {
     }
 
     @Override
+    public void grantToAllUsers(RealmModel realm, RoleModel role) {
+        // not federation-aware for now
+        session.userStorage().grantToAllUsers(realm, role);
+    }
+
+    @Override
     public void preRemove(RealmModel realm) {
         for (UserFederationProviderModel federation : realm.getUserFederationProviders()) {
             UserFederationProvider fed = getFederationProvider(federation);
diff --git a/model/api/src/main/java/org/keycloak/models/UserProvider.java b/model/api/src/main/java/org/keycloak/models/UserProvider.java
index 7d7064d..82be2fe 100755
--- a/model/api/src/main/java/org/keycloak/models/UserProvider.java
+++ b/model/api/src/main/java/org/keycloak/models/UserProvider.java
@@ -43,6 +43,8 @@ public interface UserProvider extends Provider {
     Set<FederatedIdentityModel> getFederatedIdentities(UserModel user, RealmModel realm);
     FederatedIdentityModel getFederatedIdentity(UserModel user, String socialProvider, RealmModel realm);
 
+    void grantToAllUsers(RealmModel realm, RoleModel role);
+
     void preRemove(RealmModel realm);
 
     void preRemove(RealmModel realm, UserFederationProviderModel link);
diff --git a/model/file/src/main/java/org/keycloak/models/file/FileUserProvider.java b/model/file/src/main/java/org/keycloak/models/file/FileUserProvider.java
index 8edfe3e..8c24262 100755
--- a/model/file/src/main/java/org/keycloak/models/file/FileUserProvider.java
+++ b/model/file/src/main/java/org/keycloak/models/file/FileUserProvider.java
@@ -423,6 +423,13 @@ public class FileUserProvider implements UserProvider {
     }
 
     @Override
+    public void grantToAllUsers(RealmModel realm, RoleModel role) {
+        for (UserModel user : inMemoryModel.getUsers(realm.getId())) {
+            user.grantRole(role);
+        }
+    }
+
+    @Override
     public void preRemove(RealmModel realm) {
         // Nothing to do here?  Federation links are attached to users, which are removed by InMemoryModel
     }
diff --git a/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/DefaultCacheUserProvider.java b/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/DefaultCacheUserProvider.java
index 69fc5cf..9045f91 100644
--- a/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/DefaultCacheUserProvider.java
+++ b/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/DefaultCacheUserProvider.java
@@ -304,6 +304,12 @@ public class DefaultCacheUserProvider implements CacheUserProvider {
     }
 
     @Override
+    public void grantToAllUsers(RealmModel realm, RoleModel role) {
+        realmInvalidations.add(realm.getId()); // easier to just invalidate whole realm
+        getDelegate().grantToAllUsers(realm, role);
+    }
+
+    @Override
     public void preRemove(RealmModel realm) {
         realmInvalidations.add(realm.getId());
         getDelegate().preRemove(realm);
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserRoleMappingEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserRoleMappingEntity.java
index 1ce81e8..45dfc3d 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserRoleMappingEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserRoleMappingEntity.java
@@ -23,7 +23,8 @@ import java.io.Serializable;
         @NamedQuery(name="deleteUserRoleMappingsByRealm", query="delete from  UserRoleMappingEntity mapping where mapping.user IN (select u from UserEntity u where u.realmId=:realmId)"),
         @NamedQuery(name="deleteUserRoleMappingsByRealmAndLink", query="delete from  UserRoleMappingEntity mapping where mapping.user IN (select u from UserEntity u where u.realmId=:realmId and u.federationLink=:link)"),
         @NamedQuery(name="deleteUserRoleMappingsByRole", query="delete from UserRoleMappingEntity m where m.roleId = :roleId"),
-        @NamedQuery(name="deleteUserRoleMappingsByUser", query="delete from UserRoleMappingEntity m where m.user = :user")
+        @NamedQuery(name="deleteUserRoleMappingsByUser", query="delete from UserRoleMappingEntity m where m.user = :user"),
+        @NamedQuery(name="grantRoleToAllUsers", query="insert into UserRoleMappingEntity (roleId, user) select role.id, user from RoleEntity role, UserEntity user where role.id = :roleId AND role.realm.id = :realmId AND user.realmId = :realmId")
 
 })
 @Table(name="USER_ROLE_MAPPING")
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 d4d533a..c903147 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
@@ -147,7 +147,13 @@ public class JpaUserProvider implements UserProvider {
         }
     }
 
-
+    @Override
+    public void grantToAllUsers(RealmModel realm, RoleModel role) {
+        int num = em.createNamedQuery("grantRoleToAllUsers")
+                .setParameter("realmId", realm.getId())
+                .setParameter("roleId", role.getId())
+                .executeUpdate();
+    }
 
     @Override
     public void preRemove(RealmModel realm) {
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 358e6f2..9fc9735 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
@@ -369,6 +369,19 @@ public class MongoUserProvider implements UserProvider {
     }
 
     @Override
+    public void grantToAllUsers(RealmModel realm, RoleModel role) {
+        DBObject query = new QueryBuilder()
+                .and("realmId").is(realm.getId())
+                .get();
+
+        DBObject update = new QueryBuilder()
+                .and("$push").is(new BasicDBObject("roleIds", role.getId()))
+                .get();
+
+        int count = getMongoStore().updateEntities(MongoUserEntity.class, query, update, invocationContext);
+    }
+
+    @Override
     public void preRemove(RealmModel realm) {
         DBObject query = new QueryBuilder()
                 .and("realmId").is(realm.getId())
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserModelTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserModelTest.java
index 258dd3c..6601855 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserModelTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserModelTest.java
@@ -5,6 +5,7 @@ import org.junit.Test;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.models.UserModel.RequiredAction;
 import org.keycloak.services.managers.ClientManager;
@@ -283,6 +284,36 @@ public class UserModelTest extends AbstractModelTest {
         Assert.assertNull(session.users().getUserByUsername("user1", realm));
     }
 
+    @Test
+    public void testGrantToAll() {
+        RealmModel realm1 = realmManager.createRealm("realm1");
+        RoleModel role1 = realm1.addRole("role1");
+        UserModel user1 = realmManager.getSession().users().addUser(realm1, "user1");
+        UserModel user2 = realmManager.getSession().users().addUser(realm1, "user2");
+
+        RealmModel realm2 = realmManager.createRealm("realm2");
+        UserModel realm2User1 = realmManager.getSession().users().addUser(realm2, "user1");
+
+        commit();
+
+        realm1 = realmManager.getRealmByName("realm1");
+        role1 = realm1.getRole("role1");
+        realmManager.getSession().users().grantToAllUsers(realm1, role1);
+
+        commit();
+
+        realm1 = realmManager.getRealmByName("realm1");
+        role1 = realm1.getRole("role1");
+        user1 = realmManager.getSession().users().getUserByUsername("user1", realm1);
+        user2 = realmManager.getSession().users().getUserByUsername("user2", realm1);
+        Assert.assertTrue(user1.hasRole(role1));
+        Assert.assertTrue(user2.hasRole(role1));
+
+        realm2 = realmManager.getRealmByName("realm2");
+        realm2User1 = realmManager.getSession().users().getUserByUsername("user1", realm2);
+        Assert.assertFalse(realm2User1.hasRole(role1));
+    }
+
     public static void assertEquals(UserModel expected, UserModel actual) {
         Assert.assertEquals(expected.getUsername(), actual.getUsername());
         Assert.assertEquals(expected.getCreatedTimestamp(), actual.getCreatedTimestamp());