keycloak-aplcache

composite roles 2

1/30/2014 2:28:08 AM

Details

diff --git a/model/api/src/main/java/org/keycloak/models/RoleModel.java b/model/api/src/main/java/org/keycloak/models/RoleModel.java
index c2a9507..e4cd7f5 100755
--- a/model/api/src/main/java/org/keycloak/models/RoleModel.java
+++ b/model/api/src/main/java/org/keycloak/models/RoleModel.java
@@ -30,4 +30,5 @@ public interface RoleModel {
     RoleContainerModel getContainer();
 
 
+    boolean hasRole(RoleModel role);
 }
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/ApplicationAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/ApplicationAdapter.java
index 6f46042..29dfdbd 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/ApplicationAdapter.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/ApplicationAdapter.java
@@ -261,4 +261,11 @@ public class ApplicationAdapter implements ApplicationModel {
     public void addScope(RoleModel role) {
         realm.addScopeMapping(getApplicationUser(), role);
     }
+
+    public boolean equals(Object o) {
+        if (o == null) return false;
+        if (!(o instanceof ApplicationAdapter)) return false;
+        ApplicationAdapter app = (ApplicationAdapter)o;
+        return app.getId().equals(getId());
+    }
 }
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 a627a84..82a95b5 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
@@ -897,28 +897,13 @@ public class RealmAdapter implements RealmModel {
         return new RoleAdapter(this, em, entity);
     }
 
-    protected boolean searchCompositeFor(RoleModel role, RoleModel composite, Set<RoleModel> visited) {
-        if (visited.contains(composite)) return false;
-        visited.add(composite);
-        Set<RoleModel> composites = composite.getComposites();
-        if (composites.contains(role)) return true;
-        for (RoleModel contained : composites) {
-            if (!contained.isComposite()) continue;
-            if (searchCompositeFor(role, contained, visited)) return true;
-        }
-        return false;
-    }
-
     @Override
     public boolean hasRole(UserModel user, RoleModel role) {
         Set<RoleModel> roles = getRoleMappings(user);
         if (roles.contains(role)) return true;
 
-        Set<RoleModel> visited = new HashSet<RoleModel>();
         for (RoleModel mapping : roles) {
-            if (!mapping.isComposite()) continue;
-            if (searchCompositeFor(role, mapping, visited)) return true;
-
+            if (mapping.hasRole(role)) return true;
         }
         return false;
     }
@@ -1104,4 +1089,12 @@ public class RealmAdapter implements RealmModel {
         realm.setPasswordPolicy(policy.toString());
         em.flush();
     }
+
+    public boolean equals(Object o) {
+        if (o == null) return false;
+        if (!(o instanceof RealmAdapter)) return false;
+        RealmAdapter r = (RealmAdapter)o;
+        return r.getId().equals(getId());
+    }
+
 }
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/RoleAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/RoleAdapter.java
index 87c09d0..529fc7d 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/RoleAdapter.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/RoleAdapter.java
@@ -3,6 +3,7 @@ package org.keycloak.models.jpa;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RoleContainerModel;
 import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserModel;
 import org.keycloak.models.jpa.entities.ApplicationRoleEntity;
 import org.keycloak.models.jpa.entities.RealmRoleEntity;
 import org.keycloak.models.jpa.entities.RoleEntity;
@@ -97,6 +98,27 @@ public class RoleAdapter implements RoleModel {
         return set;
     }
 
+    public static boolean searchCompositeFor(RoleModel role, RoleModel composite, Set<RoleModel> visited) {
+        if (visited.contains(composite)) return false;
+        visited.add(composite);
+        Set<RoleModel> composites = composite.getComposites();
+        if (composites.contains(role)) return true;
+        for (RoleModel contained : composites) {
+            if (!contained.isComposite()) continue;
+            if (searchCompositeFor(role, contained, visited)) return true;
+        }
+        return false;
+    }
+
+    @Override
+    public boolean hasRole(RoleModel role) {
+        if (this.equals(role)) return true;
+        if (!isComposite()) return false;
+
+        Set<RoleModel> visited = new HashSet<RoleModel>();
+        return searchCompositeFor(role, this, visited);
+    }
+
     @Override
     public RoleContainerModel getContainer() {
         if (role instanceof ApplicationRoleEntity) {
diff --git a/services/src/main/java/org/keycloak/services/managers/TokenManager.java b/services/src/main/java/org/keycloak/services/managers/TokenManager.java
index 6531942..8cdb690 100755
--- a/services/src/main/java/org/keycloak/services/managers/TokenManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/TokenManager.java
@@ -16,6 +16,7 @@ import javax.ws.rs.core.MultivaluedMap;
 import java.io.IOException;
 import java.io.UnsupportedEncodingException;
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -69,31 +70,34 @@ public class TokenManager {
         List<RoleModel> realmRolesRequested = code.getRealmRolesRequested();
         MultivaluedMap<String, RoleModel> resourceRolesRequested = code.getResourceRolesRequested();
 
-        Set<RoleModel> realmScopeMappings = realm.getRealmScopeMappings(client);
-        for (RoleModel desiredRole : realmScopeMappings) {
-            if (!realm.hasRole(user, desiredRole)) continue;
-            if (desiresScope(scopeMap, "realm", desiredRole.getName())) {
-                realmRolesRequested.add(desiredRole);
-            }
-        }
 
-        for (ApplicationModel application : realm.getApplications()) {
-            if (!desiresScopeGroup(scopeMap, application.getName())) continue;
-            Set<RoleModel> desiredRoles = application.getApplicationScopeMappings(client);
-            if (desiredRoles.isEmpty()) {
-                if (application.getApplicationUser().getLoginName().equals(client.getLoginName())) {
-                    Set<RoleModel> appRoleMappings = application.getApplicationRoleMappings(user);
-                    for (RoleModel desiredAppRole : appRoleMappings) {
-                        if (desiresScope(scopeMap, application.getName(), desiredAppRole.getName())) {
-                            resourceRolesRequested.add(application.getName(), desiredAppRole);
-                        }
+        Set<RoleModel> roleMappings = realm.getRoleMappings(user);
+        Set<RoleModel> scopeMappings = realm.getScopeMappings(client);
+        Set<RoleModel> requestedRoles = new HashSet<RoleModel>();
+
+        for (RoleModel role : roleMappings) {
+            for (RoleModel desiredRole : scopeMappings) {
+                if (desiredRole.equals(role)) {
+                    requestedRoles.add(role);
+                } else if (desiredRole.hasRole(role)) {
+                    requestedRoles.add(role);
+                } else if (role.hasRole(desiredRole)) {
+                    requestedRoles.add(desiredRole);
+                } else if (role.getContainer() instanceof ApplicationModel) {
+                    if (((ApplicationModel)role.getContainer()).getApplicationUser().getLoginName().equals(client.getLoginName())) {
+                        requestedRoles.add(role);
                     }
                 }
-            } else {
-                for (RoleModel desiredAppRole : desiredRoles) {
-                    if (realm.hasRole(user, desiredAppRole) && desiresScope(scopeMap, application.getName(), desiredAppRole.getName())) {
-                        resourceRolesRequested.add(application.getName(), desiredAppRole);
-                    }
+            }
+        }
+
+        for (RoleModel role : requestedRoles) {
+            if (role.getContainer() instanceof RealmModel && desiresScope(scopeMap, "realm", role.getName())) {
+                realmRolesRequested.add(role);
+            } else if (role.getContainer() instanceof ApplicationModel) {
+                ApplicationModel app = (ApplicationModel)role.getContainer();
+                if (desiresScope(scopeMap, app.getName(), role.getName())) {
+                    resourceRolesRequested.add(app.getName(), role);
                 }
             }
         }
@@ -166,7 +170,6 @@ public class TokenManager {
         SkeletonKeyToken token = initToken(realm, client, user);
 
         if (accessCodeEntry.getRealmRolesRequested().size() > 0) {
-            SkeletonKeyToken.Access access = new SkeletonKeyToken.Access();
             for (RoleModel role : accessCodeEntry.getRealmRolesRequested()) {
                 addComposites(token, role);
             }
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/composites/CompositeRoleTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/composites/CompositeRoleTest.java
index ddde357..d21d85f 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/composites/CompositeRoleTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/composites/CompositeRoleTest.java
@@ -58,6 +58,8 @@ public class CompositeRoleTest {
             manager.generateRealmKeys(realm);
             realmPublicKey = realm.getPublicKey();
             realm.setTokenLifespan(10000);
+            realm.setAccessCodeLifespanUserAction(1000);
+            realm.setAccessCodeLifespan(1000);
             realm.setSslNotRequired(true);
             realm.setEnabled(true);
             realm.addRequiredResourceCredential(UserCredentialModel.PASSWORD);
@@ -75,6 +77,11 @@ public class CompositeRoleTest {
             realm.updateCredential(realmComposite1User, UserCredentialModel.password("password"));
             realm.grantRole(realmComposite1User, realmComposite1);
 
+            final UserModel realmRole1User = realm.addUser("REALM_ROLE_1_USER");
+            realmRole1User.setEnabled(true);
+            realm.updateCredential(realmRole1User, UserCredentialModel.password("password"));
+            realm.grantRole(realmRole1User, realmRole1);
+
             final ApplicationModel realmComposite1Application = new ApplicationManager(manager).createApplication(realm, "REALM_COMPOSITE_1_APPLICATION");
             realmComposite1Application.setEnabled(true);
             realmComposite1Application.addScope(realmComposite1);
@@ -109,7 +116,7 @@ public class CompositeRoleTest {
     protected LoginPage loginPage;
 
     @Test
-    public void testRealmOnlyCompositeWithUserCompositeAppComposite() throws Exception {
+    public void testRealmOnlyWithUserCompositeAppComposite() throws Exception {
         oauth.realm("Test");
         oauth.realmPublicKey(realmPublicKey);
         oauth.clientId("REALM_COMPOSITE_1_APPLICATION");
@@ -132,7 +139,7 @@ public class CompositeRoleTest {
     }
 
     @Test
-    public void testRealmOnlyCompositeWithUserCompositeAppRole() throws Exception {
+    public void testRealmOnlyWithUserCompositeAppRole() throws Exception {
         oauth.realm("Test");
         oauth.realmPublicKey(realmPublicKey);
         oauth.clientId("REALM_ROLE_1_APPLICATION");
@@ -153,5 +160,29 @@ public class CompositeRoleTest {
         Assert.assertTrue(token.getRealmAccess().isUserInRole("REALM_ROLE_1"));
     }
 
+    @Test
+    public void testRealmOnlyWithUserRoleAppComposite() throws Exception {
+        oauth.realm("Test");
+        oauth.realmPublicKey(realmPublicKey);
+        oauth.clientId("REALM_COMPOSITE_1_APPLICATION");
+        oauth.doLogin("REALM_ROLE_1_USER", "password");
+
+        String code = oauth.getCurrentQuery().get("code");
+        AccessTokenResponse response = oauth.doAccessTokenRequest(code, "password");
+
+        Assert.assertEquals(200, response.getStatusCode());
+
+        Assert.assertEquals("bearer", response.getTokenType());
+
+        SkeletonKeyToken token = oauth.verifyToken(response.getAccessToken());
+
+        Assert.assertEquals("REALM_ROLE_1_USER", token.getSubject());
+
+        Assert.assertEquals(1, token.getRealmAccess().getRoles().size());
+        Assert.assertTrue(token.getRealmAccess().isUserInRole("REALM_ROLE_1"));
+    }
+
+
+
 
 }