keycloak-aplcache
Changes
model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/authorization/events/PolicyRemovedEvent.java 8(+6 -2)
model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/authorization/events/PolicyUpdatedEvent.java 8(+6 -2)
model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/authorization/PolicyAdapter.java 8(+4 -4)
model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/authorization/StoreFactoryCacheManager.java 18(+15 -3)
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) {