keycloak-aplcache

Merge pull request #4213 from pedroigor/cache-fixes Missing

6/9/2017 9:13:13 AM

Details

diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/authorization/events/PolicyRemovedEvent.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/authorization/events/PolicyRemovedEvent.java
index 759c284..4d46f81 100644
--- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/authorization/events/PolicyRemovedEvent.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/authorization/events/PolicyRemovedEvent.java
@@ -30,13 +30,17 @@ public class PolicyRemovedEvent extends InvalidationEvent implements Authorizati
     private String id;
     private String name;
     private Set<String> resources;
+    private Set<String> resourceTypes;
+    private Set<String> scopes;
     private String serverId;
 
-    public static PolicyRemovedEvent create(String id, String name, Set<String> resources, String serverId) {
+    public static PolicyRemovedEvent create(String id, String name, Set<String> resources, Set<String> resourceTypes, Set<String> scopes, String serverId) {
         PolicyRemovedEvent event = new PolicyRemovedEvent();
         event.id = id;
         event.name = name;
         event.resources = resources;
+        event.resourceTypes = resourceTypes;
+        event.scopes = scopes;
         event.serverId = serverId;
         return event;
     }
@@ -53,6 +57,6 @@ public class PolicyRemovedEvent extends InvalidationEvent implements Authorizati
 
     @Override
     public void addInvalidations(StoreFactoryCacheManager cache, Set<String> invalidations) {
-        cache.policyRemoval(id, name, resources, serverId, invalidations);
+        cache.policyRemoval(id, name, resources, resourceTypes, scopes, serverId, invalidations);
     }
 }
diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/authorization/events/PolicyUpdatedEvent.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/authorization/events/PolicyUpdatedEvent.java
index b576bda..d613c57 100644
--- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/authorization/events/PolicyUpdatedEvent.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/authorization/events/PolicyUpdatedEvent.java
@@ -30,13 +30,17 @@ public class PolicyUpdatedEvent extends InvalidationEvent implements Authorizati
     private String id;
     private String name;
     private static Set<String> resources;
+    private Set<String> resourceTypes;
+    private Set<String> scopes;
     private String serverId;
 
-    public static PolicyUpdatedEvent create(String id, String name, Set<String> resources, String serverId) {
+    public static PolicyUpdatedEvent create(String id, String name, Set<String> resources, Set<String> resourceTypes, Set<String> scopes, String serverId) {
         PolicyUpdatedEvent event = new PolicyUpdatedEvent();
         event.id = id;
         event.name = name;
         event.resources = resources;
+        event.resourceTypes = resourceTypes;
+        event.scopes = scopes;
         event.serverId = serverId;
         return event;
     }
@@ -53,6 +57,6 @@ public class PolicyUpdatedEvent extends InvalidationEvent implements Authorizati
 
     @Override
     public void addInvalidations(StoreFactoryCacheManager cache, Set<String> invalidations) {
-        cache.policyUpdated(id, name, resources, serverId, invalidations);
+        cache.policyUpdated(id, name, resources, resourceTypes, scopes, serverId, invalidations);
     }
 }
diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/authorization/PolicyAdapter.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/authorization/PolicyAdapter.java
index 970d1b9..7660c96 100644
--- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/authorization/PolicyAdapter.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/authorization/PolicyAdapter.java
@@ -47,7 +47,7 @@ public class PolicyAdapter implements Policy, CachedModel<Policy> {
     @Override
     public Policy getDelegateForUpdate() {
         if (updated == null) {
-            cacheSession.registerPolicyInvalidation(cached.getId(), cached.getName(), cached.getResourcesIds(), cached.getResourceServerId());
+            cacheSession.registerPolicyInvalidation(cached.getId(), cached.getName(), cached.getResourcesIds(), cached.getScopesIds(), cached.getResourceServerId());
             updated = cacheSession.getPolicyStoreDelegate().findById(cached.getId(), cached.getResourceServerId());
             if (updated == null) throw new IllegalStateException("Not found in database");
         }
@@ -96,7 +96,7 @@ public class PolicyAdapter implements Policy, CachedModel<Policy> {
     @Override
     public void setName(String name) {
         getDelegateForUpdate();
-        cacheSession.registerPolicyInvalidation(cached.getId(), name, cached.getResourcesIds(), cached.getResourceServerId());
+        cacheSession.registerPolicyInvalidation(cached.getId(), name, cached.getResourcesIds(), cached.getScopesIds(), cached.getResourceServerId());
         updated.setName(name);
 
     }
@@ -235,7 +235,7 @@ public class PolicyAdapter implements Policy, CachedModel<Policy> {
         getDelegateForUpdate();
         HashSet<String> resources = new HashSet<>();
         resources.add(resource.getId());
-        cacheSession.registerPolicyInvalidation(cached.getId(), cached.getName(), resources, cached.getResourceServerId());
+        cacheSession.registerPolicyInvalidation(cached.getId(), cached.getName(), resources, cached.getScopesIds(), cached.getResourceServerId());
         updated.addResource(resource);
 
     }
@@ -245,7 +245,7 @@ public class PolicyAdapter implements Policy, CachedModel<Policy> {
         getDelegateForUpdate();
         HashSet<String> resources = new HashSet<>();
         resources.add(resource.getId());
-        cacheSession.registerPolicyInvalidation(cached.getId(), cached.getName(), resources, cached.getResourceServerId());
+        cacheSession.registerPolicyInvalidation(cached.getId(), cached.getName(), resources, cached.getScopesIds(), cached.getResourceServerId());
         updated.removeResource(resource);
 
     }
diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/authorization/StoreFactoryCacheManager.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/authorization/StoreFactoryCacheManager.java
index 7943589..63eb8a7 100644
--- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/authorization/StoreFactoryCacheManager.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/authorization/StoreFactoryCacheManager.java
@@ -102,7 +102,7 @@ public class StoreFactoryCacheManager extends CacheManager {
         addInvalidations(InResourcePredicate.create().resource(id), invalidations);
     }
 
-    public void policyUpdated(String id, String name, Set<String> resources, String serverId, Set<String> invalidations) {
+    public void policyUpdated(String id, String name, Set<String> resources, Set<String> resourceTypes, Set<String> scopes, String serverId, Set<String> invalidations) {
         invalidations.add(id);
         invalidations.add(StoreFactoryCacheSession.getPolicyByNameCacheKey(name, serverId));
 
@@ -111,10 +111,22 @@ public class StoreFactoryCacheManager extends CacheManager {
                 invalidations.add(StoreFactoryCacheSession.getPolicyByResource(resource, serverId));
             }
         }
+
+        if (resourceTypes != null) {
+            for (String type : resourceTypes) {
+                invalidations.add(StoreFactoryCacheSession.getPolicyByResourceType(type, serverId));
+            }
+        }
+
+        if (scopes != null) {
+            for (String scope : scopes) {
+                invalidations.add(StoreFactoryCacheSession.getPolicyByScope(scope, serverId));
+            }
+        }
     }
 
-    public void policyRemoval(String id, String name, Set<String> resources, String serverId, Set<String> invalidations) {
-        policyUpdated(id, name, resources, serverId, invalidations);
+    public void policyRemoval(String id, String name, Set<String> resources, Set<String> resourceTypes, Set<String> scopes, String serverId, Set<String> invalidations) {
+        policyUpdated(id, name, resources, resourceTypes, scopes, serverId, invalidations);
     }
 
 
diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/authorization/StoreFactoryCacheSession.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/authorization/StoreFactoryCacheSession.java
index 3e4c205..10be78d 100644
--- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/authorization/StoreFactoryCacheSession.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/authorization/StoreFactoryCacheSession.java
@@ -23,6 +23,7 @@ import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Set;
 import java.util.function.BiFunction;
 import java.util.function.Supplier;
@@ -252,12 +253,30 @@ public class StoreFactoryCacheSession implements CachedStoreFactoryProvider {
         invalidationEvents.add(ResourceUpdatedEvent.create(id, name, type, uri, scopes, serverId));
     }
 
-    public void registerPolicyInvalidation(String id, String name, Set<String> resources, String serverId) {
-        cache.policyUpdated(id, name, resources, serverId, invalidations);
+    public void registerPolicyInvalidation(String id, String name, Set<String> resources, Set<String> scopes, String serverId) {
+        Set<String> resourceTypes = getResourceTypes(resources, serverId);
+        cache.policyUpdated(id, name, resources, resourceTypes, scopes, serverId, invalidations);
         PolicyAdapter adapter = managedPolicies.get(id);
         if (adapter != null) adapter.invalidateFlag();
 
-        invalidationEvents.add(PolicyUpdatedEvent.create(id, name, resources, serverId));
+        invalidationEvents.add(PolicyUpdatedEvent.create(id, name, resources, resourceTypes, scopes, serverId));
+    }
+
+    private Set<String> getResourceTypes(Set<String> resources, String serverId) {
+        if (resources == null) {
+            return Collections.emptySet();
+        }
+
+        return resources.stream().map(resourceId -> {
+            Resource resource = getResourceStore().findById(resourceId, serverId);
+            String type = resource.getType();
+
+            if (type != null) {
+                return type;
+            }
+
+            return null;
+        }).filter(Objects::nonNull).collect(Collectors.toSet());
     }
 
     public ResourceServerStore getResourceServerStoreDelegate() {
@@ -626,7 +645,7 @@ public class StoreFactoryCacheSession implements CachedStoreFactoryProvider {
         @Override
         public Policy create(AbstractPolicyRepresentation representation, ResourceServer resourceServer) {
             Policy policy = getPolicyStoreDelegate().create(representation, resourceServer);
-            registerPolicyInvalidation(policy.getId(), policy.getName(), policy.getResources().stream().map(resource1 -> resource1.getId()).collect(Collectors.toSet()), resourceServer.getId());
+            registerPolicyInvalidation(policy.getId(), representation.getName(), representation.getResources(), representation.getScopes(), resourceServer.getId());
             return policy;
         }
 
@@ -637,8 +656,12 @@ public class StoreFactoryCacheSession implements CachedStoreFactoryProvider {
             if (policy == null) return;
 
             cache.invalidateObject(id);
-            invalidationEvents.add(PolicyRemovedEvent.create(id, policy.getName(), policy.getResources().stream().map(resource1 -> resource1.getId()).collect(Collectors.toSet()), policy.getResourceServer().getId()));
-            cache.policyRemoval(id, policy.getName(), policy.getResources().stream().map(resource1 -> resource1.getId()).collect(Collectors.toSet()), policy.getResourceServer().getId(), invalidations);
+            Set<String> resources = policy.getResources().stream().map(resource -> resource.getId()).collect(Collectors.toSet());
+            ResourceServer resourceServer = policy.getResourceServer();
+            Set<String> resourceTypes = getResourceTypes(resources, resourceServer.getId());
+            Set<String> scopes = policy.getScopes().stream().map(scope -> scope.getId()).collect(Collectors.toSet());
+            invalidationEvents.add(PolicyRemovedEvent.create(id, policy.getName(), resources, resourceTypes, scopes, resourceServer.getId()));
+            cache.policyRemoval(id, policy.getName(), resources, resourceTypes, scopes, resourceServer.getId(), invalidations);
             getPolicyStoreDelegate().delete(id);
 
         }
diff --git a/server-spi-private/src/main/java/org/keycloak/authorization/AuthorizationProvider.java b/server-spi-private/src/main/java/org/keycloak/authorization/AuthorizationProvider.java
index 8a55ff1..644b90a 100644
--- a/server-spi-private/src/main/java/org/keycloak/authorization/AuthorizationProvider.java
+++ b/server-spi-private/src/main/java/org/keycloak/authorization/AuthorizationProvider.java
@@ -21,14 +21,17 @@ package org.keycloak.authorization;
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
 
 import org.keycloak.authorization.model.Policy;
+import org.keycloak.authorization.model.Resource;
 import org.keycloak.authorization.model.ResourceServer;
+import org.keycloak.authorization.model.Scope;
 import org.keycloak.authorization.permission.evaluator.Evaluators;
 import org.keycloak.authorization.policy.evaluation.DefaultPolicyEvaluator;
 import org.keycloak.authorization.policy.provider.PolicyProvider;
 import org.keycloak.authorization.policy.provider.PolicyProviderFactory;
-import org.keycloak.authorization.store.AuthorizationStoreFactory;
 import org.keycloak.authorization.store.PolicyStore;
 import org.keycloak.authorization.store.ResourceServerStore;
 import org.keycloak.authorization.store.ResourceStore;
@@ -37,7 +40,6 @@ import org.keycloak.authorization.store.StoreFactory;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.cache.authorization.CachedStoreFactoryProvider;
-import org.keycloak.models.cache.authorization.CachedStoreProviderFactory;
 import org.keycloak.models.utils.RepresentationToModel;
 import org.keycloak.provider.Provider;
 import org.keycloak.representations.idm.authorization.AbstractPolicyRepresentation;
@@ -143,6 +145,61 @@ public final class AuthorizationProvider implements Provider {
                 return new PolicyStore() {
                     @Override
                     public Policy create(AbstractPolicyRepresentation representation, ResourceServer resourceServer) {
+                        Set<String> resources = representation.getResources();
+
+                        if (resources != null) {
+                            representation.setResources(resources.stream().map(id -> {
+                                Resource resource = getResourceStore().findById(id, resourceServer.getId());
+
+                                if (resource == null) {
+                                    resource = getResourceStore().findByName(id, resourceServer.getId());
+                                }
+
+                                if (resource == null) {
+                                    throw new RuntimeException("Resource [" + id + "] does not exist");
+                                }
+
+                                return resource.getId();
+                            }).collect(Collectors.toSet()));
+                        }
+
+                        Set<String> scopes = representation.getScopes();
+
+                        if (scopes != null) {
+                            representation.setScopes(scopes.stream().map(id -> {
+                                Scope scope = getScopeStore().findById(id, resourceServer.getId());
+
+                                if (scope == null) {
+                                    scope = getScopeStore().findByName(id, resourceServer.getId());
+                                }
+
+                                if (scope == null) {
+                                    throw new RuntimeException("Scope [" + id + "] does not exist");
+                                }
+
+                                return scope.getId();
+                            }).collect(Collectors.toSet()));
+                        }
+
+
+                        Set<String> policies = representation.getPolicies();
+
+                        if (policies != null) {
+                            representation.setPolicies(policies.stream().map(id -> {
+                                Policy policy = getPolicyStore().findById(id, resourceServer.getId());
+
+                                if (policy == null) {
+                                    policy = getPolicyStore().findByName(id, resourceServer.getId());
+                                }
+
+                                if (policy == null) {
+                                    throw new RuntimeException("Policy [" + id + "] does not exist");
+                                }
+
+                                return policy.getId();
+                            }).collect(Collectors.toSet()));
+                        }
+
                         return RepresentationToModel.toModel(representation, AuthorizationProvider.this, policyStore.create(representation, resourceServer));
                     }
 
diff --git a/server-spi-private/src/main/java/org/keycloak/models/utils/RepresentationToModel.java b/server-spi-private/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
index e102d3d..4a4b4fb 100755
--- a/server-spi-private/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
+++ b/server-spi-private/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
@@ -2171,13 +2171,13 @@ public class RepresentationToModel {
     private static void updateResources(Set<String> resourceIds, Policy policy, StoreFactory storeFactory) {
         if (resourceIds != null) {
             if (resourceIds.isEmpty()) {
-                for (Scope scope : new HashSet<Scope>(policy.getScopes())) {
-                    policy.removeScope(scope);
+                for (Resource resource : new HashSet<>(policy.getResources())) {
+                    policy.removeResource(resource);
                 }
             }
             for (String resourceId : resourceIds) {
                 boolean hasResource = false;
-                for (Resource resourceModel : new HashSet<Resource>(policy.getResources())) {
+                for (Resource resourceModel : new HashSet<>(policy.getResources())) {
                     if (resourceModel.getId().equals(resourceId) || resourceModel.getName().equals(resourceId)) {
                         hasResource = true;
                     }
@@ -2196,7 +2196,7 @@ public class RepresentationToModel {
                 }
             }
 
-            for (Resource resourceModel : new HashSet<Resource>(policy.getResources())) {
+            for (Resource resourceModel : new HashSet<>(policy.getResources())) {
                 boolean hasResource = false;
 
                 for (String resourceId : resourceIds) {