commit
d22a284df1
76 changed files with 3340 additions and 2247 deletions
|
@ -107,7 +107,7 @@ public class ClientPolicyProviderFactory implements PolicyProviderFactory<Client
|
||||||
if (clients.isEmpty()) {
|
if (clients.isEmpty()) {
|
||||||
policyStore.delete(policy.getId());
|
policyStore.delete(policy.getId());
|
||||||
} else {
|
} else {
|
||||||
policy.getConfig().put("clients", JsonSerialization.writeValueAsString(clients));
|
policy.putConfig("clients", JsonSerialization.writeValueAsString(clients));
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException("Error while synchronizing clients with policy [" + policy.getName() + "].", e);
|
throw new RuntimeException("Error while synchronizing clients with policy [" + policy.getName() + "].", e);
|
||||||
|
@ -152,11 +152,7 @@ public class ClientPolicyProviderFactory implements PolicyProviderFactory<Client
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Map<String, String> config = policy.getConfig();
|
policy.putConfig("clients", JsonSerialization.writeValueAsString(updatedClients));
|
||||||
|
|
||||||
config.put("clients", JsonSerialization.writeValueAsString(updatedClients));
|
|
||||||
|
|
||||||
policy.setConfig(config);
|
|
||||||
} catch (IOException cause) {
|
} catch (IOException cause) {
|
||||||
throw new RuntimeException("Failed to serialize clients", cause);
|
throw new RuntimeException("Failed to serialize clients", cause);
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,9 +70,7 @@ public class JSPolicyProviderFactory implements PolicyProviderFactory<JSPolicyRe
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updatePolicy(Policy policy, String code) {
|
private void updatePolicy(Policy policy, String code) {
|
||||||
Map<String, String> config = policy.getConfig();
|
policy.putConfig("code", code);
|
||||||
config.put("code", code);
|
|
||||||
policy.setConfig(config);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package org.keycloak.authorization.policy.provider.resource;
|
package org.keycloak.authorization.policy.provider.resource;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.keycloak.Config;
|
import org.keycloak.Config;
|
||||||
|
@ -64,7 +65,7 @@ public class ResourcePolicyProviderFactory implements PolicyProviderFactory<Reso
|
||||||
//TODO: remove this check once we migrate to new API
|
//TODO: remove this check once we migrate to new API
|
||||||
if (ResourcePermissionRepresentation.class.equals(representation.getClass())) {
|
if (ResourcePermissionRepresentation.class.equals(representation.getClass())) {
|
||||||
ResourcePermissionRepresentation resourcePermission = ResourcePermissionRepresentation.class.cast(representation);
|
ResourcePermissionRepresentation resourcePermission = ResourcePermissionRepresentation.class.cast(representation);
|
||||||
Map<String, String> config = policy.getConfig();
|
Map<String, String> config = new HashMap(policy.getConfig());
|
||||||
|
|
||||||
config.compute("defaultResourceType", (key, value) -> {
|
config.compute("defaultResourceType", (key, value) -> {
|
||||||
String resourceType = resourcePermission.getResourceType();
|
String resourceType = resourcePermission.getResourceType();
|
||||||
|
|
|
@ -163,11 +163,7 @@ public class RolePolicyProviderFactory implements PolicyProviderFactory<RolePoli
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Map<String, String> config = policy.getConfig();
|
policy.putConfig("roles", JsonSerialization.writeValueAsString(updatedRoles));
|
||||||
|
|
||||||
config.put("roles", JsonSerialization.writeValueAsString(updatedRoles));
|
|
||||||
|
|
||||||
policy.setConfig(config);
|
|
||||||
} catch (IOException cause) {
|
} catch (IOException cause) {
|
||||||
throw new RuntimeException("Failed to serialize roles", cause);
|
throw new RuntimeException("Failed to serialize roles", cause);
|
||||||
}
|
}
|
||||||
|
@ -224,9 +220,7 @@ public class RolePolicyProviderFactory implements PolicyProviderFactory<RolePoli
|
||||||
if (roles.isEmpty()) {
|
if (roles.isEmpty()) {
|
||||||
policyStore.delete(policy.getId());
|
policyStore.delete(policy.getId());
|
||||||
} else {
|
} else {
|
||||||
Map<String, String> config = policy.getConfig();
|
policy.putConfig("roles", JsonSerialization.writeValueAsString(roles));
|
||||||
config.put("roles", JsonSerialization.writeValueAsString(roles));
|
|
||||||
policy.setConfig(config);
|
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException("Error while synchronizing roles with policy [" + policy.getName() + "].", e);
|
throw new RuntimeException("Error while synchronizing roles with policy [" + policy.getName() + "].", e);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package org.keycloak.authorization.policy.provider.time;
|
package org.keycloak.authorization.policy.provider.time;
|
||||||
|
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.keycloak.Config;
|
import org.keycloak.Config;
|
||||||
|
@ -118,7 +119,7 @@ public class TimePolicyProviderFactory implements PolicyProviderFactory<TimePoli
|
||||||
validateFormat(noa);
|
validateFormat(noa);
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, String> config = policy.getConfig();
|
Map<String, String> config = new HashMap(policy.getConfig());
|
||||||
|
|
||||||
config.compute("nbf", (s, s2) -> nbf != null ? nbf : null);
|
config.compute("nbf", (s, s2) -> nbf != null ? nbf : null);
|
||||||
config.compute("noa", (s, s2) -> noa != null ? noa : null);
|
config.compute("noa", (s, s2) -> noa != null ? noa : null);
|
||||||
|
|
|
@ -138,11 +138,8 @@ public class UserPolicyProviderFactory implements PolicyProviderFactory<UserPoli
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Map<String, String> config = policy.getConfig();
|
|
||||||
|
|
||||||
config.put("users", JsonSerialization.writeValueAsString(updatedUsers));
|
policy.putConfig("users", JsonSerialization.writeValueAsString(updatedUsers));
|
||||||
|
|
||||||
policy.setConfig(config);
|
|
||||||
} catch (IOException cause) {
|
} catch (IOException cause) {
|
||||||
throw new RuntimeException("Failed to serialize users", cause);
|
throw new RuntimeException("Failed to serialize users", cause);
|
||||||
}
|
}
|
||||||
|
@ -181,7 +178,7 @@ public class UserPolicyProviderFactory implements PolicyProviderFactory<UserPoli
|
||||||
if (users.isEmpty()) {
|
if (users.isEmpty()) {
|
||||||
policyStore.delete(policy.getId());
|
policyStore.delete(policy.getId());
|
||||||
} else {
|
} else {
|
||||||
policy.getConfig().put("users", JsonSerialization.writeValueAsString(users));
|
policy.putConfig("users", JsonSerialization.writeValueAsString(users));
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException("Error while synchronizing users with policy [" + policy.getName() + "].", e);
|
throw new RuntimeException("Error while synchronizing users with policy [" + policy.getName() + "].", e);
|
||||||
|
|
|
@ -120,17 +120,15 @@ public class DroolsPolicyProviderFactory implements PolicyProviderFactory<RulePo
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateConfig(Policy policy, RulePolicyRepresentation representation) {
|
private void updateConfig(Policy policy, RulePolicyRepresentation representation) {
|
||||||
Map<String, String> config = policy.getConfig();
|
|
||||||
|
|
||||||
config.put("mavenArtifactGroupId", representation.getArtifactGroupId());
|
policy.putConfig("mavenArtifactGroupId", representation.getArtifactGroupId());
|
||||||
config.put("mavenArtifactId", representation.getArtifactId());
|
policy.putConfig("mavenArtifactId", representation.getArtifactId());
|
||||||
config.put("mavenArtifactVersion", representation.getArtifactVersion());
|
policy.putConfig("mavenArtifactVersion", representation.getArtifactVersion());
|
||||||
config.put("scannerPeriod", representation.getScannerPeriod());
|
policy.putConfig("scannerPeriod", representation.getScannerPeriod());
|
||||||
config.put("scannerPeriodUnit", representation.getScannerPeriodUnit());
|
policy.putConfig("scannerPeriodUnit", representation.getScannerPeriodUnit());
|
||||||
config.put("sessionName", representation.getSessionName());
|
policy.putConfig("sessionName", representation.getSessionName());
|
||||||
config.put("moduleName", representation.getModuleName());
|
policy.putConfig("moduleName", representation.getModuleName());
|
||||||
|
|
||||||
policy.setConfig(config);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void update(Policy policy) {
|
void update(Policy policy) {
|
||||||
|
|
|
@ -126,6 +126,16 @@ public class DefaultInfinispanConnectionProviderFactory implements InfinispanCon
|
||||||
cacheManager.getCache(InfinispanConnectionProvider.KEYS_CACHE_NAME, true);
|
cacheManager.getCache(InfinispanConnectionProvider.KEYS_CACHE_NAME, true);
|
||||||
cacheManager.getCache(InfinispanConnectionProvider.ACTION_TOKEN_CACHE, true);
|
cacheManager.getCache(InfinispanConnectionProvider.ACTION_TOKEN_CACHE, true);
|
||||||
|
|
||||||
|
long authzRevisionsMaxEntries = cacheManager.getCache(InfinispanConnectionProvider.AUTHORIZATION_CACHE_NAME).getCacheConfiguration().eviction().maxEntries();
|
||||||
|
authzRevisionsMaxEntries = authzRevisionsMaxEntries > 0
|
||||||
|
? 2 * authzRevisionsMaxEntries
|
||||||
|
: InfinispanConnectionProvider.AUTHORIZATION_REVISIONS_CACHE_DEFAULT_MAX;
|
||||||
|
|
||||||
|
cacheManager.defineConfiguration(InfinispanConnectionProvider.AUTHORIZATION_REVISIONS_CACHE_NAME, getRevisionCacheConfig(authzRevisionsMaxEntries));
|
||||||
|
cacheManager.getCache(InfinispanConnectionProvider.AUTHORIZATION_REVISIONS_CACHE_NAME, true);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
logger.debugv("Using container managed Infinispan cache container, lookup={1}", cacheContainerLookup);
|
logger.debugv("Using container managed Infinispan cache container, lookup={1}", cacheContainerLookup);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException("Failed to retrieve cache container", e);
|
throw new RuntimeException("Failed to retrieve cache container", e);
|
||||||
|
@ -157,6 +167,7 @@ public class DefaultInfinispanConnectionProviderFactory implements InfinispanCon
|
||||||
Configuration modelCacheConfiguration = modelCacheConfigBuilder.build();
|
Configuration modelCacheConfiguration = modelCacheConfigBuilder.build();
|
||||||
|
|
||||||
cacheManager.defineConfiguration(InfinispanConnectionProvider.REALM_CACHE_NAME, modelCacheConfiguration);
|
cacheManager.defineConfiguration(InfinispanConnectionProvider.REALM_CACHE_NAME, modelCacheConfiguration);
|
||||||
|
cacheManager.defineConfiguration(InfinispanConnectionProvider.AUTHORIZATION_CACHE_NAME, modelCacheConfiguration);
|
||||||
cacheManager.defineConfiguration(InfinispanConnectionProvider.USER_CACHE_NAME, modelCacheConfiguration);
|
cacheManager.defineConfiguration(InfinispanConnectionProvider.USER_CACHE_NAME, modelCacheConfiguration);
|
||||||
|
|
||||||
ConfigurationBuilder sessionConfigBuilder = new ConfigurationBuilder();
|
ConfigurationBuilder sessionConfigBuilder = new ConfigurationBuilder();
|
||||||
|
@ -186,14 +197,12 @@ public class DefaultInfinispanConnectionProviderFactory implements InfinispanCon
|
||||||
cacheManager.defineConfiguration(InfinispanConnectionProvider.SESSION_CACHE_NAME, sessionCacheConfiguration);
|
cacheManager.defineConfiguration(InfinispanConnectionProvider.SESSION_CACHE_NAME, sessionCacheConfiguration);
|
||||||
cacheManager.defineConfiguration(InfinispanConnectionProvider.OFFLINE_SESSION_CACHE_NAME, sessionCacheConfiguration);
|
cacheManager.defineConfiguration(InfinispanConnectionProvider.OFFLINE_SESSION_CACHE_NAME, sessionCacheConfiguration);
|
||||||
cacheManager.defineConfiguration(InfinispanConnectionProvider.LOGIN_FAILURE_CACHE_NAME, sessionCacheConfiguration);
|
cacheManager.defineConfiguration(InfinispanConnectionProvider.LOGIN_FAILURE_CACHE_NAME, sessionCacheConfiguration);
|
||||||
cacheManager.defineConfiguration(InfinispanConnectionProvider.AUTHORIZATION_CACHE_NAME, sessionCacheConfiguration);
|
|
||||||
cacheManager.defineConfiguration(InfinispanConnectionProvider.AUTHENTICATION_SESSIONS_CACHE_NAME, sessionCacheConfiguration);
|
cacheManager.defineConfiguration(InfinispanConnectionProvider.AUTHENTICATION_SESSIONS_CACHE_NAME, sessionCacheConfiguration);
|
||||||
|
|
||||||
// Retrieve caches to enforce rebalance
|
// Retrieve caches to enforce rebalance
|
||||||
cacheManager.getCache(InfinispanConnectionProvider.SESSION_CACHE_NAME, true);
|
cacheManager.getCache(InfinispanConnectionProvider.SESSION_CACHE_NAME, true);
|
||||||
cacheManager.getCache(InfinispanConnectionProvider.OFFLINE_SESSION_CACHE_NAME, true);
|
cacheManager.getCache(InfinispanConnectionProvider.OFFLINE_SESSION_CACHE_NAME, true);
|
||||||
cacheManager.getCache(InfinispanConnectionProvider.LOGIN_FAILURE_CACHE_NAME, true);
|
cacheManager.getCache(InfinispanConnectionProvider.LOGIN_FAILURE_CACHE_NAME, true);
|
||||||
cacheManager.getCache(InfinispanConnectionProvider.AUTHORIZATION_CACHE_NAME, true);
|
|
||||||
cacheManager.getCache(InfinispanConnectionProvider.AUTHENTICATION_SESSIONS_CACHE_NAME, true);
|
cacheManager.getCache(InfinispanConnectionProvider.AUTHENTICATION_SESSIONS_CACHE_NAME, true);
|
||||||
|
|
||||||
ConfigurationBuilder replicationConfigBuilder = new ConfigurationBuilder();
|
ConfigurationBuilder replicationConfigBuilder = new ConfigurationBuilder();
|
||||||
|
@ -236,6 +245,14 @@ public class DefaultInfinispanConnectionProviderFactory implements InfinispanCon
|
||||||
|
|
||||||
cacheManager.defineConfiguration(InfinispanConnectionProvider.ACTION_TOKEN_CACHE, getActionTokenCacheConfig());
|
cacheManager.defineConfiguration(InfinispanConnectionProvider.ACTION_TOKEN_CACHE, getActionTokenCacheConfig());
|
||||||
cacheManager.getCache(InfinispanConnectionProvider.ACTION_TOKEN_CACHE, true);
|
cacheManager.getCache(InfinispanConnectionProvider.ACTION_TOKEN_CACHE, true);
|
||||||
|
|
||||||
|
long authzRevisionsMaxEntries = cacheManager.getCache(InfinispanConnectionProvider.AUTHORIZATION_CACHE_NAME).getCacheConfiguration().eviction().maxEntries();
|
||||||
|
authzRevisionsMaxEntries = authzRevisionsMaxEntries > 0
|
||||||
|
? 2 * authzRevisionsMaxEntries
|
||||||
|
: InfinispanConnectionProvider.AUTHORIZATION_REVISIONS_CACHE_DEFAULT_MAX;
|
||||||
|
|
||||||
|
cacheManager.defineConfiguration(InfinispanConnectionProvider.AUTHORIZATION_REVISIONS_CACHE_NAME, getRevisionCacheConfig(authzRevisionsMaxEntries));
|
||||||
|
cacheManager.getCache(InfinispanConnectionProvider.AUTHORIZATION_REVISIONS_CACHE_NAME, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Configuration getRevisionCacheConfig(long maxEntries) {
|
private Configuration getRevisionCacheConfig(long maxEntries) {
|
||||||
|
|
|
@ -39,6 +39,8 @@ public interface InfinispanConnectionProvider extends Provider {
|
||||||
String AUTHENTICATION_SESSIONS_CACHE_NAME = "authenticationSessions";
|
String AUTHENTICATION_SESSIONS_CACHE_NAME = "authenticationSessions";
|
||||||
String WORK_CACHE_NAME = "work";
|
String WORK_CACHE_NAME = "work";
|
||||||
String AUTHORIZATION_CACHE_NAME = "authorization";
|
String AUTHORIZATION_CACHE_NAME = "authorization";
|
||||||
|
String AUTHORIZATION_REVISIONS_CACHE_NAME = "authorizationRevisions";
|
||||||
|
int AUTHORIZATION_REVISIONS_CACHE_DEFAULT_MAX = 20000;
|
||||||
|
|
||||||
String ACTION_TOKEN_CACHE = "actionTokens";
|
String ACTION_TOKEN_CACHE = "actionTokens";
|
||||||
int ACTION_TOKEN_CACHE_DEFAULT_MAX = -1;
|
int ACTION_TOKEN_CACHE_DEFAULT_MAX = -1;
|
||||||
|
|
|
@ -1,73 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
* and other contributors as indicated by the @author tags.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.keycloak.models.authorization.infinispan;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.keycloak.authorization.store.StoreFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
|
||||||
*/
|
|
||||||
public abstract class AbstractCachedStore {
|
|
||||||
|
|
||||||
private final InfinispanStoreFactoryProvider cacheStoreFactory;
|
|
||||||
private final StoreFactory storeFactory;
|
|
||||||
|
|
||||||
AbstractCachedStore(InfinispanStoreFactoryProvider cacheStoreFactory, StoreFactory storeFactory) {
|
|
||||||
this.cacheStoreFactory = cacheStoreFactory;
|
|
||||||
this.storeFactory = storeFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void addInvalidation(String cacheKeyForPolicy) {
|
|
||||||
getCachedStoreFactory().addInvalidation(cacheKeyForPolicy);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected <E> E putCacheEntry(String resourceServerId, String cacheKeyForPolicy, E cachedPolicy) {
|
|
||||||
cacheStoreFactory.putCacheEntry(resourceServerId, cacheKeyForPolicy, Arrays.asList(cachedPolicy));
|
|
||||||
return cachedPolicy;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected List<Object> resolveCacheEntry(String resourceServerId, String cacheKeyForPolicy) {
|
|
||||||
return cacheStoreFactory.resolveCachedEntry(resourceServerId, cacheKeyForPolicy);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void removeCachedEntry(String resourceServerId, String key) {
|
|
||||||
getCachedStoreFactory().removeCachedEntry(resourceServerId, key);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void invalidate(String resourceServerId) {
|
|
||||||
cacheStoreFactory.invalidate(resourceServerId);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected StoreFactory getStoreFactory() {
|
|
||||||
return this.storeFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean isInvalid(String cacheKey) {
|
|
||||||
return cacheStoreFactory.isInvalid(cacheKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected InfinispanStoreFactoryProvider.CacheTransaction getTransaction() {
|
|
||||||
return cacheStoreFactory.getTransaction();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected InfinispanStoreFactoryProvider getCachedStoreFactory() {
|
|
||||||
return cacheStoreFactory;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,500 +0,0 @@
|
||||||
/*
|
|
||||||
* JBoss, Home of Professional Open Source.
|
|
||||||
* Copyright 2016 Red Hat, Inc., and individual contributors
|
|
||||||
* as indicated by the @author tags.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.keycloak.models.authorization.infinispan;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
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.store.PolicyStore;
|
|
||||||
import org.keycloak.authorization.store.StoreFactory;
|
|
||||||
import org.keycloak.models.authorization.infinispan.entities.CachedPolicy;
|
|
||||||
import org.keycloak.representations.idm.authorization.AbstractPolicyRepresentation;
|
|
||||||
import org.keycloak.representations.idm.authorization.DecisionStrategy;
|
|
||||||
import org.keycloak.representations.idm.authorization.Logic;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
|
||||||
*/
|
|
||||||
public class CachedPolicyStore extends AbstractCachedStore implements PolicyStore {
|
|
||||||
|
|
||||||
private static final String POLICY_CACHE_PREFIX = "pc-";
|
|
||||||
|
|
||||||
private PolicyStore delegate;
|
|
||||||
|
|
||||||
public CachedPolicyStore(InfinispanStoreFactoryProvider cacheStoreFactory, StoreFactory storeFactory) {
|
|
||||||
super(cacheStoreFactory, storeFactory);
|
|
||||||
this.delegate = storeFactory.getPolicyStore();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Policy create(AbstractPolicyRepresentation representation, ResourceServer resourceServer) {
|
|
||||||
Policy policy = getDelegate().create(representation, getStoreFactory().getResourceServerStore().findById(resourceServer.getId()));
|
|
||||||
String id = policy.getId();
|
|
||||||
|
|
||||||
addInvalidation(getCacheKeyForPolicy(policy.getId()));
|
|
||||||
addInvalidation(getCacheKeyForPolicyName(policy.getName()));
|
|
||||||
addInvalidation(getCacheKeyForPolicyType(policy.getType()));
|
|
||||||
|
|
||||||
configureTransaction(resourceServer, id);
|
|
||||||
|
|
||||||
return createAdapter(new CachedPolicy(policy));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void delete(String id) {
|
|
||||||
Policy policy = getDelegate().findById(id, null);
|
|
||||||
if (policy == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
addInvalidation(getCacheKeyForPolicy(policy.getId()));
|
|
||||||
addInvalidation(getCacheKeyForPolicyName(policy.getName()));
|
|
||||||
addInvalidation(getCacheKeyForPolicyType(policy.getType()));
|
|
||||||
|
|
||||||
getDelegate().delete(id);
|
|
||||||
configureTransaction(policy.getResourceServer(), policy.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Policy findById(String id, String resourceServerId) {
|
|
||||||
if (resourceServerId == null) {
|
|
||||||
return getDelegate().findById(id, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isInvalid(getCacheKeyForPolicy(id))) {
|
|
||||||
return getDelegate().findById(id, resourceServerId);
|
|
||||||
}
|
|
||||||
|
|
||||||
String cacheKeyForPolicy = getCacheKeyForPolicy(id);
|
|
||||||
List<Object> cached = resolveCacheEntry(resourceServerId, cacheKeyForPolicy);
|
|
||||||
|
|
||||||
if (cached == null) {
|
|
||||||
Policy policy = getDelegate().findById(id, resourceServerId);
|
|
||||||
|
|
||||||
if (policy != null) {
|
|
||||||
return createAdapter(putCacheEntry(resourceServerId, cacheKeyForPolicy, new CachedPolicy(policy)));
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return createAdapter(CachedPolicy.class.cast(cached.get(0)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Policy findByName(String name, String resourceServerId) {
|
|
||||||
String cacheKey = getCacheKeyForPolicyName(name);
|
|
||||||
|
|
||||||
if (isInvalid(cacheKey)) {
|
|
||||||
return getDelegate().findByName(name, resourceServerId);
|
|
||||||
}
|
|
||||||
|
|
||||||
return cacheResult(resourceServerId, cacheKey, () -> {
|
|
||||||
Policy policy = getDelegate().findByName(name, resourceServerId);
|
|
||||||
|
|
||||||
if (policy == null) {
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
return Arrays.asList(policy);
|
|
||||||
}).stream().findFirst().orElse(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<Policy> findByResourceServer(String resourceServerId) {
|
|
||||||
return getDelegate().findByResourceServer(resourceServerId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<Policy> findByResourceServer(Map<String, String[]> attributes, String resourceServerId, int firstResult, int maxResult) {
|
|
||||||
return getDelegate().findByResourceServer(attributes, resourceServerId, firstResult, maxResult);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<Policy> findByResource(String resourceId, String resourceServerId) {
|
|
||||||
String cacheKey = getCacheKeyForResource(resourceId);
|
|
||||||
|
|
||||||
if (isInvalid(cacheKey)) {
|
|
||||||
return getDelegate().findByResource(resourceId, resourceServerId);
|
|
||||||
}
|
|
||||||
|
|
||||||
return cacheResult(resourceServerId, cacheKey, () -> getDelegate().findByResource(resourceId, resourceServerId));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<Policy> findByResourceType(String resourceType, String resourceServerId) {
|
|
||||||
String cacheKey = getCacheKeyForResourceType(resourceType);
|
|
||||||
|
|
||||||
if (isInvalid(cacheKey)) {
|
|
||||||
return getDelegate().findByResourceType(resourceType, resourceServerId);
|
|
||||||
}
|
|
||||||
|
|
||||||
return cacheResult(resourceServerId, cacheKey, () -> getDelegate().findByResourceType(resourceType, resourceServerId));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<Policy> findByScopeIds(List<String> scopeIds, String resourceServerId) {
|
|
||||||
List<Policy> policies = new ArrayList<>();
|
|
||||||
|
|
||||||
for (String scopeId : scopeIds) {
|
|
||||||
String cacheKey = getCacheForScope(scopeId);
|
|
||||||
|
|
||||||
if (isInvalid(cacheKey)) {
|
|
||||||
policies.addAll(getDelegate().findByScopeIds(Arrays.asList(scopeId), resourceServerId));
|
|
||||||
} else {
|
|
||||||
policies.addAll(cacheResult(resourceServerId, cacheKey, () -> getDelegate().findByScopeIds(Arrays.asList(scopeId), resourceServerId)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return policies;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<Policy> findByType(String type, String resourceServerId) {
|
|
||||||
String cacheKey = getCacheKeyForPolicyType(type);
|
|
||||||
|
|
||||||
if (isInvalid(cacheKey)) {
|
|
||||||
return getDelegate().findByType(type, resourceServerId);
|
|
||||||
}
|
|
||||||
|
|
||||||
return cacheResult(resourceServerId, cacheKey, () -> getDelegate().findByType(type, resourceServerId));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<Policy> findDependentPolicies(String id, String resourceServerId) {
|
|
||||||
return getDelegate().findDependentPolicies(id, resourceServerId);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getCacheKeyForPolicy(String id) {
|
|
||||||
return new StringBuilder().append(POLICY_CACHE_PREFIX).append("id-").append(id).toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getCacheKeyForPolicyType(String type) {
|
|
||||||
return new StringBuilder().append(POLICY_CACHE_PREFIX).append("findByType-").append(type).toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getCacheKeyForPolicyName(String name) {
|
|
||||||
return new StringBuilder().append(POLICY_CACHE_PREFIX).append("findByName-").append(name).toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getCacheKeyForResourceType(String resourceType) {
|
|
||||||
return new StringBuilder().append(POLICY_CACHE_PREFIX).append("findByResourceType-").append(resourceType).toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getCacheForScope(String scopeId) {
|
|
||||||
return new StringBuilder().append(POLICY_CACHE_PREFIX).append("findByScopeIds-").append(scopeId).toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getCacheKeyForResource(String resourceId) {
|
|
||||||
return new StringBuilder().append(POLICY_CACHE_PREFIX).append("findByResource-").append(resourceId).toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Policy createAdapter(CachedPolicy cached) {
|
|
||||||
return new Policy() {
|
|
||||||
|
|
||||||
private Set<Scope> scopes;
|
|
||||||
private Set<Resource> resources;
|
|
||||||
private Set<Policy> associatedPolicies;
|
|
||||||
private Policy updated;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getId() {
|
|
||||||
return cached.getId();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getType() {
|
|
||||||
return cached.getType();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DecisionStrategy getDecisionStrategy() {
|
|
||||||
return cached.getDecisionStrategy();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setDecisionStrategy(DecisionStrategy decisionStrategy) {
|
|
||||||
getDelegateForUpdate().setDecisionStrategy(decisionStrategy);
|
|
||||||
cached.setDecisionStrategy(decisionStrategy);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Logic getLogic() {
|
|
||||||
return cached.getLogic();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setLogic(Logic logic) {
|
|
||||||
getDelegateForUpdate().setLogic(logic);
|
|
||||||
cached.setLogic(logic);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, String> getConfig() {
|
|
||||||
return new HashMap<>(cached.getConfig());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setConfig(Map<String, String> config) {
|
|
||||||
String resourceType = config.get("defaultResourceType");
|
|
||||||
|
|
||||||
if (resourceType != null) {
|
|
||||||
addInvalidation(getCacheKeyForResourceType(resourceType));
|
|
||||||
String cachedResourceType = cached.getConfig().get("defaultResourceType");
|
|
||||||
if (cachedResourceType != null && !resourceType.equals(cachedResourceType)) {
|
|
||||||
addInvalidation(getCacheKeyForResourceType(cachedResourceType));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getDelegateForUpdate().setConfig(config);
|
|
||||||
cached.setConfig(config);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return cached.getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setName(String name) {
|
|
||||||
addInvalidation(getCacheKeyForPolicyName(name));
|
|
||||||
addInvalidation(getCacheKeyForPolicyName(cached.getName()));
|
|
||||||
getDelegateForUpdate().setName(name);
|
|
||||||
cached.setName(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getDescription() {
|
|
||||||
return cached.getDescription();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setDescription(String description) {
|
|
||||||
getDelegateForUpdate().setDescription(description);
|
|
||||||
cached.setDescription(description);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ResourceServer getResourceServer() {
|
|
||||||
return getCachedStoreFactory().getResourceServerStore().findById(cached.getResourceServerId());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addScope(Scope scope) {
|
|
||||||
Scope model = getStoreFactory().getScopeStore().findById(scope.getId(), cached.getResourceServerId());
|
|
||||||
addInvalidation(getCacheForScope(model.getId()));
|
|
||||||
getDelegateForUpdate().addScope(model);
|
|
||||||
cached.addScope(scope);
|
|
||||||
scopes.add(scope);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void removeScope(Scope scope) {
|
|
||||||
Scope model = getStoreFactory().getScopeStore().findById(scope.getId(), cached.getResourceServerId());
|
|
||||||
addInvalidation(getCacheForScope(scope.getId()));
|
|
||||||
getDelegateForUpdate().removeScope(model);
|
|
||||||
cached.removeScope(scope);
|
|
||||||
scopes.remove(scope);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addAssociatedPolicy(Policy associatedPolicy) {
|
|
||||||
getDelegateForUpdate().addAssociatedPolicy(getStoreFactory().getPolicyStore().findById(associatedPolicy.getId(), cached.getResourceServerId()));
|
|
||||||
cached.addAssociatedPolicy(associatedPolicy);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void removeAssociatedPolicy(Policy associatedPolicy) {
|
|
||||||
getDelegateForUpdate().removeAssociatedPolicy(getStoreFactory().getPolicyStore().findById(associatedPolicy.getId(), cached.getResourceServerId()));
|
|
||||||
cached.removeAssociatedPolicy(associatedPolicy);
|
|
||||||
associatedPolicies.remove(associatedPolicy);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addResource(Resource resource) {
|
|
||||||
Resource model = getStoreFactory().getResourceStore().findById(resource.getId(), cached.getResourceServerId());
|
|
||||||
|
|
||||||
addInvalidation(getCacheKeyForResource(model.getId()));
|
|
||||||
|
|
||||||
if (model.getType() != null) {
|
|
||||||
addInvalidation(getCacheKeyForResourceType(model.getType()));
|
|
||||||
}
|
|
||||||
|
|
||||||
getDelegateForUpdate().addResource(model);
|
|
||||||
cached.addResource(resource);
|
|
||||||
resources.add(resource);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void removeResource(Resource resource) {
|
|
||||||
Resource model = getStoreFactory().getResourceStore().findById(resource.getId(), cached.getResourceServerId());
|
|
||||||
|
|
||||||
addInvalidation(getCacheKeyForResource(model.getId()));
|
|
||||||
|
|
||||||
if (model.getType() != null) {
|
|
||||||
addInvalidation(getCacheKeyForResourceType(model.getType()));
|
|
||||||
}
|
|
||||||
|
|
||||||
getDelegateForUpdate().removeResource(model);
|
|
||||||
cached.removeResource(resource);
|
|
||||||
resources.remove(resource);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<Policy> getAssociatedPolicies() {
|
|
||||||
if (associatedPolicies == null || updated != null) {
|
|
||||||
associatedPolicies = new HashSet<>();
|
|
||||||
|
|
||||||
for (String id : cached.getAssociatedPoliciesIds()) {
|
|
||||||
Policy policy = findById(id, cached.getResourceServerId());
|
|
||||||
|
|
||||||
if (policy != null) {
|
|
||||||
associatedPolicies.add(policy);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return associatedPolicies;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<Resource> getResources() {
|
|
||||||
if (resources == null || updated != null) {
|
|
||||||
resources = new HashSet<>();
|
|
||||||
|
|
||||||
for (String id : cached.getResourcesIds()) {
|
|
||||||
Resource resource = getCachedStoreFactory().getResourceStore().findById(id, cached.getResourceServerId());
|
|
||||||
|
|
||||||
if (resource != null) {
|
|
||||||
resources.add(resource);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return resources;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<Scope> getScopes() {
|
|
||||||
if (scopes == null || updated != null) {
|
|
||||||
scopes = new HashSet<>();
|
|
||||||
|
|
||||||
for (String id : cached.getScopesIds()) {
|
|
||||||
Scope scope = getCachedStoreFactory().getScopeStore().findById(id, cached.getResourceServerId());
|
|
||||||
|
|
||||||
if (scope != null) {
|
|
||||||
scopes.add(scope);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return scopes;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (o == this) return true;
|
|
||||||
|
|
||||||
if (getId() == null) return false;
|
|
||||||
|
|
||||||
if (!Policy.class.isInstance(o)) return false;
|
|
||||||
|
|
||||||
Policy that = (Policy) o;
|
|
||||||
|
|
||||||
if (!getId().equals(that.getId())) return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return getId()!=null ? getId().hashCode() : super.hashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Policy getDelegateForUpdate() {
|
|
||||||
if (this.updated == null) {
|
|
||||||
this.updated = getDelegate().findById(getId(), cached.getResourceServerId());
|
|
||||||
if (this.updated == null) throw new IllegalStateException("Not found in database");
|
|
||||||
addInvalidation(getCacheKeyForPolicy(updated.getId()));
|
|
||||||
configureTransaction(updated.getResourceServer(), updated.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.updated;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<Policy> cacheResult(String resourceServerId, String key, Supplier<List<Policy>> provider) {
|
|
||||||
List<Object> cached = getCachedStoreFactory().computeIfCachedEntryAbsent(resourceServerId, key, (Function<String, List<Object>>) o -> {
|
|
||||||
List<Policy> result = provider.get();
|
|
||||||
|
|
||||||
if (result.isEmpty()) {
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
return result.stream().map(policy -> policy.getId()).collect(Collectors.toList());
|
|
||||||
});
|
|
||||||
|
|
||||||
if (cached == null) {
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
return cached.stream().map(id -> findById(id.toString(), resourceServerId)).collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void configureTransaction(ResourceServer resourceServer, String id) {
|
|
||||||
getTransaction().whenRollback(() -> removeCachedEntry(resourceServer.getId(), getCacheKeyForPolicy(id)));
|
|
||||||
getTransaction().whenCommit(() -> invalidate(resourceServer.getId()));
|
|
||||||
}
|
|
||||||
|
|
||||||
private PolicyStore getDelegate() {
|
|
||||||
return delegate;
|
|
||||||
}
|
|
||||||
|
|
||||||
void addInvalidations(Object object) {
|
|
||||||
if (Resource.class.isInstance(object)) {
|
|
||||||
Resource resource = (Resource) object;
|
|
||||||
addInvalidation(getCacheKeyForResource(resource.getId()));
|
|
||||||
String type = resource.getType();
|
|
||||||
|
|
||||||
if (type != null) {
|
|
||||||
addInvalidation(getCacheKeyForResourceType(type));
|
|
||||||
}
|
|
||||||
} else if (Scope.class.isInstance(object)) {
|
|
||||||
Scope scope = (Scope) object;
|
|
||||||
addInvalidation(getCacheForScope(scope.getId()));
|
|
||||||
} else {
|
|
||||||
throw new RuntimeException("Unexpected notification [" + object + "]");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,172 +0,0 @@
|
||||||
/*
|
|
||||||
* JBoss, Home of Professional Open Source.
|
|
||||||
* Copyright 2016 Red Hat, Inc., and individual contributors
|
|
||||||
* as indicated by the @author tags.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.keycloak.models.authorization.infinispan;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.keycloak.authorization.model.ResourceServer;
|
|
||||||
import org.keycloak.authorization.store.ResourceServerStore;
|
|
||||||
import org.keycloak.authorization.store.StoreFactory;
|
|
||||||
import org.keycloak.models.authorization.infinispan.entities.CachedResourceServer;
|
|
||||||
import org.keycloak.representations.idm.authorization.PolicyEnforcementMode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
|
||||||
*/
|
|
||||||
public class CachedResourceServerStore extends AbstractCachedStore implements ResourceServerStore {
|
|
||||||
|
|
||||||
private static final String RS_PREFIX = "rs-";
|
|
||||||
|
|
||||||
private final ResourceServerStore delegate;
|
|
||||||
|
|
||||||
public CachedResourceServerStore(InfinispanStoreFactoryProvider cachedStoreFactory, StoreFactory storeFactory) {
|
|
||||||
super(cachedStoreFactory, storeFactory);
|
|
||||||
this.delegate = storeFactory.getResourceServerStore();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ResourceServer create(String clientId) {
|
|
||||||
ResourceServer resourceServer = getDelegate().create(clientId);
|
|
||||||
|
|
||||||
getTransaction().whenCommit(() -> getCachedStoreFactory().removeEntries(resourceServer));
|
|
||||||
getTransaction().whenRollback(() -> removeCachedEntry(resourceServer.getId(), getCacheKeyForResourceServer(resourceServer.getId())));
|
|
||||||
|
|
||||||
return createAdapter(new CachedResourceServer(resourceServer));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void delete(String id) {
|
|
||||||
ResourceServer resourceServer = getDelegate().findById(id);
|
|
||||||
|
|
||||||
if (resourceServer != null) {
|
|
||||||
getDelegate().delete(id);
|
|
||||||
getTransaction().whenCommit(() -> getCachedStoreFactory().removeEntries(resourceServer));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ResourceServer findById(String id) {
|
|
||||||
String cacheKey = getCacheKeyForResourceServer(id);
|
|
||||||
|
|
||||||
if (isInvalid(cacheKey)) {
|
|
||||||
return getDelegate().findById(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Object> cached = resolveCacheEntry(id, cacheKey);
|
|
||||||
|
|
||||||
if (cached == null) {
|
|
||||||
ResourceServer resourceServer = getDelegate().findById(id);
|
|
||||||
|
|
||||||
if (resourceServer != null) {
|
|
||||||
return createAdapter(putCacheEntry(id, cacheKey, new CachedResourceServer(resourceServer)));
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return createAdapter(CachedResourceServer.class.cast(cached.get(0)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ResourceServer findByClient(String id) {
|
|
||||||
String cacheKey = getCacheKeyForResourceServerClientId(id);
|
|
||||||
|
|
||||||
if (isInvalid(cacheKey)) {
|
|
||||||
return getDelegate().findByClient(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Object> cached = resolveCacheEntry(id, cacheKey);
|
|
||||||
|
|
||||||
if (cached == null) {
|
|
||||||
ResourceServer resourceServer = getDelegate().findByClient(id);
|
|
||||||
|
|
||||||
if (resourceServer != null) {
|
|
||||||
return findById(putCacheEntry(id, cacheKey, resourceServer.getId()));
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return findById(cached.get(0).toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getCacheKeyForResourceServer(String id) {
|
|
||||||
return new StringBuilder(RS_PREFIX).append("id-").append(id).toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getCacheKeyForResourceServerClientId(String id) {
|
|
||||||
return new StringBuilder(RS_PREFIX).append("findByClientId-").append(id).toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private ResourceServerStore getDelegate() {
|
|
||||||
return this.delegate;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ResourceServer createAdapter(ResourceServer cached) {
|
|
||||||
return new ResourceServer() {
|
|
||||||
|
|
||||||
private ResourceServer updated;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getId() {
|
|
||||||
return cached.getId();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getClientId() {
|
|
||||||
return cached.getClientId();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isAllowRemoteResourceManagement() {
|
|
||||||
return cached.isAllowRemoteResourceManagement();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setAllowRemoteResourceManagement(boolean allowRemoteResourceManagement) {
|
|
||||||
getDelegateForUpdate().setAllowRemoteResourceManagement(allowRemoteResourceManagement);
|
|
||||||
cached.setAllowRemoteResourceManagement(allowRemoteResourceManagement);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PolicyEnforcementMode getPolicyEnforcementMode() {
|
|
||||||
return cached.getPolicyEnforcementMode();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setPolicyEnforcementMode(PolicyEnforcementMode enforcementMode) {
|
|
||||||
getDelegateForUpdate().setPolicyEnforcementMode(enforcementMode);
|
|
||||||
cached.setPolicyEnforcementMode(enforcementMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
private ResourceServer getDelegateForUpdate() {
|
|
||||||
if (this.updated == null) {
|
|
||||||
this.updated = getDelegate().findById(getId());
|
|
||||||
if (this.updated == null) throw new IllegalStateException("Not found in database");
|
|
||||||
addInvalidation(getCacheKeyForResourceServer(updated.getId()));
|
|
||||||
getTransaction().whenCommit(() -> {
|
|
||||||
invalidate(updated.getId());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.updated;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,321 +0,0 @@
|
||||||
/*
|
|
||||||
* JBoss, Home of Professional Open Source.
|
|
||||||
* Copyright 2016 Red Hat, Inc., and individual contributors
|
|
||||||
* as indicated by the @author tags.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.keycloak.models.authorization.infinispan;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import org.keycloak.authorization.model.Resource;
|
|
||||||
import org.keycloak.authorization.model.ResourceServer;
|
|
||||||
import org.keycloak.authorization.model.Scope;
|
|
||||||
import org.keycloak.authorization.store.ResourceStore;
|
|
||||||
import org.keycloak.authorization.store.StoreFactory;
|
|
||||||
import org.keycloak.models.authorization.infinispan.entities.CachedResource;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
|
||||||
*/
|
|
||||||
public class CachedResourceStore extends AbstractCachedStore implements ResourceStore {
|
|
||||||
|
|
||||||
private static final String RESOURCE_CACHE_PREFIX = "rs-";
|
|
||||||
|
|
||||||
private ResourceStore delegate;
|
|
||||||
|
|
||||||
public CachedResourceStore(InfinispanStoreFactoryProvider cacheStoreFactory, StoreFactory storeFactory) {
|
|
||||||
super(cacheStoreFactory, storeFactory);
|
|
||||||
delegate = storeFactory.getResourceStore();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Resource create(String name, ResourceServer resourceServer, String owner) {
|
|
||||||
Resource resource = getDelegate().create(name, getStoreFactory().getResourceServerStore().findById(resourceServer.getId()), owner);
|
|
||||||
|
|
||||||
addInvalidation(getCacheKeyForResource(resource.getId()));
|
|
||||||
addInvalidation(getCacheKeyForResourceName(resource.getName()));
|
|
||||||
addInvalidation(getCacheKeyForOwner(owner));
|
|
||||||
|
|
||||||
getCachedStoreFactory().getPolicyStore().addInvalidations(resource);
|
|
||||||
|
|
||||||
getTransaction().whenRollback(() -> removeCachedEntry(resourceServer.getId(), getCacheKeyForResource(resource.getId())));
|
|
||||||
getTransaction().whenCommit(() -> invalidate(resourceServer.getId()));
|
|
||||||
|
|
||||||
return createAdapter(new CachedResource(resource));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void delete(String id) {
|
|
||||||
Resource resource = getDelegate().findById(id, null);
|
|
||||||
|
|
||||||
if (resource == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ResourceServer resourceServer = resource.getResourceServer();
|
|
||||||
|
|
||||||
addInvalidation(getCacheKeyForResource(resource.getId()));
|
|
||||||
addInvalidation(getCacheKeyForResourceName(resource.getName()));
|
|
||||||
addInvalidation(getCacheKeyForOwner(resource.getOwner()));
|
|
||||||
addInvalidation(getCacheKeyForUri(resource.getUri()));
|
|
||||||
getCachedStoreFactory().getPolicyStore().addInvalidations(resource);
|
|
||||||
|
|
||||||
getDelegate().delete(id);
|
|
||||||
|
|
||||||
getTransaction().whenCommit(() -> {
|
|
||||||
invalidate(resourceServer.getId());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Resource findById(String id, String resourceServerId) {
|
|
||||||
String cacheKeyForResource = getCacheKeyForResource(id);
|
|
||||||
|
|
||||||
if (isInvalid(cacheKeyForResource)) {
|
|
||||||
return getDelegate().findById(id, resourceServerId);
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Object> cached = resolveCacheEntry(resourceServerId, cacheKeyForResource);
|
|
||||||
|
|
||||||
if (cached == null) {
|
|
||||||
Resource resource = getDelegate().findById(id, resourceServerId);
|
|
||||||
|
|
||||||
if (resource != null) {
|
|
||||||
return createAdapter(putCacheEntry(resourceServerId, cacheKeyForResource, new CachedResource(resource)));
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return createAdapter(CachedResource.class.cast(cached.get(0)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<Resource> findByOwner(String ownerId, String resourceServerId) {
|
|
||||||
String cacheKey = getCacheKeyForOwner(ownerId);
|
|
||||||
|
|
||||||
if (isInvalid(cacheKey)) {
|
|
||||||
return getDelegate().findByOwner(ownerId, resourceServerId);
|
|
||||||
}
|
|
||||||
|
|
||||||
return cacheResult(resourceServerId, cacheKey, () -> getDelegate().findByOwner(ownerId, resourceServerId));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<Resource> findByUri(String uri, String resourceServerId) {
|
|
||||||
String cacheKey = getCacheKeyForUri(uri);
|
|
||||||
|
|
||||||
if (isInvalid(cacheKey)) {
|
|
||||||
return getDelegate().findByUri(uri, resourceServerId);
|
|
||||||
}
|
|
||||||
|
|
||||||
return cacheResult(resourceServerId, cacheKey, () -> getDelegate().findByUri(uri, resourceServerId));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<Resource> findByResourceServer(String resourceServerId) {
|
|
||||||
return getDelegate().findByResourceServer(resourceServerId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<Resource> findByResourceServer(Map<String, String[]> attributes, String resourceServerId, int firstResult, int maxResult) {
|
|
||||||
return getDelegate().findByResourceServer(attributes, resourceServerId, firstResult, maxResult);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<Resource> findByScope(List<String> id, String resourceServerId) {
|
|
||||||
return getDelegate().findByScope(id, resourceServerId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Resource findByName(String name, String resourceServerId) {
|
|
||||||
String cacheKey = getCacheKeyForResourceName(name);
|
|
||||||
|
|
||||||
if (isInvalid(cacheKey)) {
|
|
||||||
return getDelegate().findByName(name, resourceServerId);
|
|
||||||
}
|
|
||||||
|
|
||||||
return cacheResult(resourceServerId, cacheKey, () -> {
|
|
||||||
Resource resource = getDelegate().findByName(name, resourceServerId);
|
|
||||||
|
|
||||||
if (resource == null) {
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
return Arrays.asList(resource);
|
|
||||||
}).stream().findFirst().orElse(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<Resource> findByType(String type, String resourceServerId) {
|
|
||||||
return getDelegate().findByType(type, resourceServerId);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getCacheKeyForResource(String id) {
|
|
||||||
return new StringBuilder(RESOURCE_CACHE_PREFIX).append("id-").append(id).toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getCacheKeyForResourceName(String name) {
|
|
||||||
return new StringBuilder(RESOURCE_CACHE_PREFIX).append("findByName-").append(name).toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getCacheKeyForOwner(String name) {
|
|
||||||
return new StringBuilder(RESOURCE_CACHE_PREFIX).append("findByOwner-").append(name).toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getCacheKeyForUri(String uri) {
|
|
||||||
return new StringBuilder(RESOURCE_CACHE_PREFIX).append("findByUri-").append(uri).toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private ResourceStore getDelegate() {
|
|
||||||
return this.delegate;
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<Resource> cacheResult(String resourceServerId, String key, Supplier<List<Resource>> provider) {
|
|
||||||
List<Object> cached = getCachedStoreFactory().computeIfCachedEntryAbsent(resourceServerId, key, (Function<String, List<Object>>) o -> {
|
|
||||||
List<Resource> result = provider.get();
|
|
||||||
|
|
||||||
if (result.isEmpty()) {
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
return result.stream().map(policy -> policy.getId()).collect(Collectors.toList());
|
|
||||||
});
|
|
||||||
|
|
||||||
if (cached == null) {
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
return cached.stream().map(id -> findById(id.toString(), resourceServerId)).collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
private Resource createAdapter(CachedResource cached) {
|
|
||||||
return new Resource() {
|
|
||||||
|
|
||||||
private List<Scope> scopes;
|
|
||||||
private Resource updated;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getId() {
|
|
||||||
return cached.getId();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return cached.getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setName(String name) {
|
|
||||||
addInvalidation(getCacheKeyForResourceName(name));
|
|
||||||
addInvalidation(getCacheKeyForResourceName(cached.getName()));
|
|
||||||
getDelegateForUpdate().setName(name);
|
|
||||||
cached.setName(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getUri() {
|
|
||||||
return cached.getUri();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setUri(String uri) {
|
|
||||||
addInvalidation(getCacheKeyForUri(uri));
|
|
||||||
addInvalidation(getCacheKeyForUri(cached.getUri()));
|
|
||||||
getDelegateForUpdate().setUri(uri);
|
|
||||||
cached.setUri(uri);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getType() {
|
|
||||||
return cached.getType();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setType(String type) {
|
|
||||||
getCachedStoreFactory().getPolicyStore().addInvalidations(cached);
|
|
||||||
getDelegateForUpdate().setType(type);
|
|
||||||
cached.setType(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<Scope> getScopes() {
|
|
||||||
if (scopes == null) {
|
|
||||||
scopes = new ArrayList<>();
|
|
||||||
|
|
||||||
for (String id : cached.getScopesIds()) {
|
|
||||||
Scope scope = getCachedStoreFactory().getScopeStore().findById(id, cached.getResourceServerId());
|
|
||||||
|
|
||||||
if (scope != null) {
|
|
||||||
scopes.add(scope);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return scopes;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getIconUri() {
|
|
||||||
return cached.getIconUri();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setIconUri(String iconUri) {
|
|
||||||
getDelegateForUpdate().setIconUri(iconUri);
|
|
||||||
cached.setIconUri(iconUri);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ResourceServer getResourceServer() {
|
|
||||||
return getCachedStoreFactory().getResourceServerStore().findById(cached.getResourceServerId());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getOwner() {
|
|
||||||
return cached.getOwner();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateScopes(Set<Scope> scopes) {
|
|
||||||
getDelegateForUpdate().updateScopes(scopes.stream().map(scope -> getStoreFactory().getScopeStore().findById(scope.getId(), cached.getResourceServerId())).collect(Collectors.toSet()));
|
|
||||||
cached.updateScopes(scopes);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Resource getDelegateForUpdate() {
|
|
||||||
if (this.updated == null) {
|
|
||||||
String resourceServerId = cached.getResourceServerId();
|
|
||||||
this.updated = getDelegate().findById(getId(), resourceServerId);
|
|
||||||
if (this.updated == null) throw new IllegalStateException("Not found in database");
|
|
||||||
addInvalidation(getCacheKeyForResource(updated.getId()));
|
|
||||||
getCachedStoreFactory().getPolicyStore().addInvalidations(updated);
|
|
||||||
getTransaction().whenCommit(() -> invalidate(resourceServerId));
|
|
||||||
getTransaction().whenRollback(() -> removeCachedEntry(resourceServerId, getCacheKeyForResource(cached.getId())));
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.updated;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,231 +0,0 @@
|
||||||
/*
|
|
||||||
* JBoss, Home of Professional Open Source.
|
|
||||||
* Copyright 2016 Red Hat, Inc., and individual contributors
|
|
||||||
* as indicated by the @author tags.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.keycloak.models.authorization.infinispan;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import org.keycloak.authorization.model.ResourceServer;
|
|
||||||
import org.keycloak.authorization.model.Scope;
|
|
||||||
import org.keycloak.authorization.store.ScopeStore;
|
|
||||||
import org.keycloak.authorization.store.StoreFactory;
|
|
||||||
import org.keycloak.models.authorization.infinispan.entities.CachedScope;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
|
||||||
*/
|
|
||||||
public class CachedScopeStore extends AbstractCachedStore implements ScopeStore {
|
|
||||||
|
|
||||||
private static final String SCOPE_CACHE_PREFIX = "scp-";
|
|
||||||
|
|
||||||
private final ScopeStore delegate;
|
|
||||||
|
|
||||||
public CachedScopeStore(InfinispanStoreFactoryProvider cacheStoreFactory, StoreFactory storeFactory) {
|
|
||||||
super(cacheStoreFactory, storeFactory);
|
|
||||||
this.delegate = storeFactory.getScopeStore();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Scope create(String name, ResourceServer resourceServer) {
|
|
||||||
Scope scope = getDelegate().create(name, getStoreFactory().getResourceServerStore().findById(resourceServer.getId()));
|
|
||||||
|
|
||||||
addInvalidation(getCacheKeyForScope(scope.getId()));
|
|
||||||
addInvalidation(getCacheKeyForScopeName(scope.getName()));
|
|
||||||
getCachedStoreFactory().getPolicyStore().addInvalidations(scope);
|
|
||||||
|
|
||||||
getTransaction().whenRollback(() -> removeCachedEntry(resourceServer.getId(), getCacheKeyForScope(scope.getId())));
|
|
||||||
getTransaction().whenCommit(() -> invalidate(resourceServer.getId()));
|
|
||||||
|
|
||||||
return createAdapter(new CachedScope(scope));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void delete(String id) {
|
|
||||||
Scope scope = getDelegate().findById(id, null);
|
|
||||||
|
|
||||||
if (scope == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ResourceServer resourceServer = scope.getResourceServer();
|
|
||||||
|
|
||||||
addInvalidation(getCacheKeyForScope(scope.getId()));
|
|
||||||
addInvalidation(getCacheKeyForScopeName(scope.getName()));
|
|
||||||
getCachedStoreFactory().getPolicyStore().addInvalidations(scope);
|
|
||||||
|
|
||||||
getDelegate().delete(id);
|
|
||||||
|
|
||||||
getTransaction().whenCommit(() -> invalidate(resourceServer.getId()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Scope findById(String id, String resourceServerId) {
|
|
||||||
String cacheKey = getCacheKeyForScope(id);
|
|
||||||
|
|
||||||
if (isInvalid(cacheKey)) {
|
|
||||||
return getDelegate().findById(id, resourceServerId);
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Object> cached = resolveCacheEntry(resourceServerId, cacheKey);
|
|
||||||
|
|
||||||
if (cached == null) {
|
|
||||||
Scope scope = getDelegate().findById(id, resourceServerId);
|
|
||||||
|
|
||||||
if (scope != null) {
|
|
||||||
return createAdapter(putCacheEntry(resourceServerId, cacheKey, new CachedScope(scope)));
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return createAdapter(CachedScope.class.cast(cached.get(0)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Scope findByName(String name, String resourceServerId) {
|
|
||||||
String cacheKey = getCacheKeyForScopeName(name);
|
|
||||||
|
|
||||||
if (isInvalid(cacheKey)) {
|
|
||||||
return getDelegate().findByName(name, resourceServerId);
|
|
||||||
}
|
|
||||||
|
|
||||||
return cacheResult(resourceServerId, cacheKey, () -> {
|
|
||||||
Scope scope = getDelegate().findByName(name, resourceServerId);
|
|
||||||
|
|
||||||
if (scope == null) {
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
return Arrays.asList(scope);
|
|
||||||
}).stream().findFirst().orElse(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<Scope> findByResourceServer(String id) {
|
|
||||||
return getDelegate().findByResourceServer(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<Scope> findByResourceServer(Map<String, String[]> attributes, String resourceServerId, int firstResult, int maxResult) {
|
|
||||||
return getDelegate().findByResourceServer(attributes, resourceServerId, firstResult, maxResult);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getCacheKeyForScope(String id) {
|
|
||||||
return new StringBuilder(SCOPE_CACHE_PREFIX).append("id-").append(id).toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getCacheKeyForScopeName(String name) {
|
|
||||||
return new StringBuilder(SCOPE_CACHE_PREFIX).append("findByName-").append(name).toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private ScopeStore getDelegate() {
|
|
||||||
return this.delegate;
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<Scope> cacheResult(String resourceServerId, String key, Supplier<List<Scope>> provider) {
|
|
||||||
List<Object> cached = getCachedStoreFactory().computeIfCachedEntryAbsent(resourceServerId, key, (Function<String, List<Object>>) o -> {
|
|
||||||
List<Scope> result = provider.get();
|
|
||||||
|
|
||||||
if (result.isEmpty()) {
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
return result.stream().map(policy -> policy.getId()).collect(Collectors.toList());
|
|
||||||
});
|
|
||||||
|
|
||||||
if (cached == null) {
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
return cached.stream().map(id -> findById(id.toString(), resourceServerId)).collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
private Scope createAdapter(CachedScope cached) {
|
|
||||||
return new Scope() {
|
|
||||||
|
|
||||||
private Scope updated;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getId() {
|
|
||||||
return cached.getId();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return cached.getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setName(String name) {
|
|
||||||
addInvalidation(getCacheKeyForScopeName(name));
|
|
||||||
addInvalidation(getCacheKeyForScopeName(cached.getName()));
|
|
||||||
getDelegateForUpdate().setName(name);
|
|
||||||
cached.setName(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getIconUri() {
|
|
||||||
return cached.getIconUri();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setIconUri(String iconUri) {
|
|
||||||
getDelegateForUpdate().setIconUri(iconUri);
|
|
||||||
cached.setIconUri(iconUri);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ResourceServer getResourceServer() {
|
|
||||||
return getCachedStoreFactory().getResourceServerStore().findById(cached.getResourceServerId());
|
|
||||||
}
|
|
||||||
|
|
||||||
private Scope getDelegateForUpdate() {
|
|
||||||
if (this.updated == null) {
|
|
||||||
this.updated = getDelegate().findById(getId(), cached.getResourceServerId());
|
|
||||||
if (this.updated == null) throw new IllegalStateException("Not found in database");
|
|
||||||
addInvalidation(getCacheKeyForScope(updated.getId()));
|
|
||||||
getCachedStoreFactory().getPolicyStore().addInvalidations(updated);
|
|
||||||
getTransaction().whenCommit(() -> invalidate(cached.getResourceServerId()));
|
|
||||||
getTransaction().whenRollback(() -> removeCachedEntry(cached.getResourceServerId(), getCacheKeyForScope(cached.getId())));
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.updated;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) return true;
|
|
||||||
if (o == null || !Scope.class.isInstance(o)) return false;
|
|
||||||
Scope that = (Scope) o;
|
|
||||||
return Objects.equals(getId(), that.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hash(getId());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,166 +0,0 @@
|
||||||
/*
|
|
||||||
* JBoss, Home of Professional Open Source.
|
|
||||||
* Copyright 2016 Red Hat, Inc., and individual contributors
|
|
||||||
* as indicated by the @author tags.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.keycloak.models.authorization.infinispan;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
import org.keycloak.authorization.model.ResourceServer;
|
|
||||||
import org.keycloak.authorization.store.ResourceServerStore;
|
|
||||||
import org.keycloak.authorization.store.ResourceStore;
|
|
||||||
import org.keycloak.authorization.store.ScopeStore;
|
|
||||||
import org.keycloak.authorization.store.StoreFactory;
|
|
||||||
import org.keycloak.models.KeycloakSession;
|
|
||||||
import org.keycloak.models.KeycloakTransaction;
|
|
||||||
import org.keycloak.models.cache.authorization.CachedStoreFactoryProvider;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
|
||||||
*/
|
|
||||||
public class InfinispanStoreFactoryProvider implements CachedStoreFactoryProvider {
|
|
||||||
|
|
||||||
private final CacheTransaction transaction;
|
|
||||||
private final CachedResourceStore resourceStore;
|
|
||||||
private final CachedScopeStore scopeStore;
|
|
||||||
private final CachedPolicyStore policyStore;
|
|
||||||
private final KeycloakSession session;
|
|
||||||
private final StoreFactoryCacheManager cacheManager;
|
|
||||||
private ResourceServerStore resourceServerStore;
|
|
||||||
private Set<String> invalidations = new HashSet<>();
|
|
||||||
|
|
||||||
public InfinispanStoreFactoryProvider(KeycloakSession session, StoreFactoryCacheManager cacheManager) {
|
|
||||||
this.session = session;
|
|
||||||
this.cacheManager = cacheManager;
|
|
||||||
this.transaction = new CacheTransaction();
|
|
||||||
session.getTransactionManager().enlistAfterCompletion(transaction);
|
|
||||||
StoreFactory delegate = session.getProvider(StoreFactory.class);
|
|
||||||
resourceStore = new CachedResourceStore(this, delegate);
|
|
||||||
resourceServerStore = new CachedResourceServerStore(this, delegate);
|
|
||||||
scopeStore = new CachedScopeStore(this, delegate);
|
|
||||||
policyStore = new CachedPolicyStore(this, delegate);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ResourceStore getResourceStore() {
|
|
||||||
return resourceStore;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ResourceServerStore getResourceServerStore() {
|
|
||||||
return resourceServerStore;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ScopeStore getScopeStore() {
|
|
||||||
return scopeStore;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CachedPolicyStore getPolicyStore() {
|
|
||||||
return policyStore;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void addInvalidation(String cacheKey) {
|
|
||||||
invalidations.add(cacheKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean isInvalid(String cacheKeyForPolicy) {
|
|
||||||
return invalidations.contains(cacheKeyForPolicy);
|
|
||||||
}
|
|
||||||
|
|
||||||
void invalidate(String resourceServerId) {
|
|
||||||
cacheManager.invalidate(session, resourceServerId, invalidations);
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Object> resolveCachedEntry(String resourceServerId, String cacheKeyForPolicy) {
|
|
||||||
return cacheManager.resolveResourceServerCache(resourceServerId).get(cacheKeyForPolicy);
|
|
||||||
}
|
|
||||||
|
|
||||||
void putCacheEntry(String resourceServerId, String key, List<Object> entry) {
|
|
||||||
cacheManager.resolveResourceServerCache(resourceServerId).put(key, entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Object> computeIfCachedEntryAbsent(String resourceServerId, String key, Function<String, List<Object>> function) {
|
|
||||||
return cacheManager.resolveResourceServerCache(resourceServerId).computeIfAbsent(key, function);
|
|
||||||
}
|
|
||||||
|
|
||||||
CacheTransaction getTransaction() {
|
|
||||||
return transaction;
|
|
||||||
}
|
|
||||||
|
|
||||||
void removeCachedEntry(String id, String key) {
|
|
||||||
cacheManager.resolveResourceServerCache(id).remove(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
void removeEntries(ResourceServer resourceServer) {
|
|
||||||
cacheManager.removeAll(session, resourceServer);
|
|
||||||
}
|
|
||||||
|
|
||||||
static class CacheTransaction implements KeycloakTransaction {
|
|
||||||
|
|
||||||
private List<Runnable> completeTasks = new ArrayList<>();
|
|
||||||
private List<Runnable> rollbackTasks = new ArrayList<>();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void begin() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void commit() {
|
|
||||||
this.completeTasks.forEach(task -> task.run());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void rollback() {
|
|
||||||
this.rollbackTasks.forEach(task -> task.run());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setRollbackOnly() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean getRollbackOnly() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isActive() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void whenCommit(Runnable task) {
|
|
||||||
this.completeTasks.add(task);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void whenRollback(Runnable task) {
|
|
||||||
this.rollbackTasks.add(task);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,89 +0,0 @@
|
||||||
/*
|
|
||||||
* JBoss, Home of Professional Open Source.
|
|
||||||
* Copyright 2016 Red Hat, Inc., and individual contributors
|
|
||||||
* as indicated by the @author tags.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.keycloak.models.authorization.infinispan;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.infinispan.Cache;
|
|
||||||
import org.keycloak.Config;
|
|
||||||
import org.keycloak.cluster.ClusterProvider;
|
|
||||||
import org.keycloak.connections.infinispan.InfinispanConnectionProvider;
|
|
||||||
import org.keycloak.models.KeycloakSession;
|
|
||||||
import org.keycloak.models.KeycloakSessionFactory;
|
|
||||||
import org.keycloak.models.authorization.infinispan.events.AuthorizationInvalidationEvent;
|
|
||||||
import org.keycloak.models.cache.authorization.CachedStoreFactoryProvider;
|
|
||||||
import org.keycloak.models.cache.authorization.CachedStoreProviderFactory;
|
|
||||||
import org.keycloak.provider.EnvironmentDependentProviderFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
|
||||||
*/
|
|
||||||
public class InfinispanStoreProviderFactory implements CachedStoreProviderFactory, EnvironmentDependentProviderFactory {
|
|
||||||
|
|
||||||
private StoreFactoryCacheManager cacheManager;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CachedStoreFactoryProvider create(KeycloakSession session) {
|
|
||||||
return new InfinispanStoreFactoryProvider(session, cacheManager);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void init(Config.Scope config) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void postInit(KeycloakSessionFactory factory) {
|
|
||||||
KeycloakSession session = factory.create();
|
|
||||||
|
|
||||||
try {
|
|
||||||
InfinispanConnectionProvider provider = session.getProvider(InfinispanConnectionProvider.class);
|
|
||||||
Cache<String, Map<String, List<Object>>> cache = provider.getCache(InfinispanConnectionProvider.AUTHORIZATION_CACHE_NAME);
|
|
||||||
ClusterProvider clusterProvider = session.getProvider(ClusterProvider.class);
|
|
||||||
|
|
||||||
cacheManager = new StoreFactoryCacheManager(cache);
|
|
||||||
|
|
||||||
clusterProvider.registerListener(ClusterProvider.ALL, event -> {
|
|
||||||
if (event instanceof AuthorizationInvalidationEvent) {
|
|
||||||
cacheManager.invalidate(AuthorizationInvalidationEvent.class.cast(event));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} finally {
|
|
||||||
if (session != null) {
|
|
||||||
session.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getId() {
|
|
||||||
return "infinispan-authz-store-factory";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isSupported() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,72 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
* and other contributors as indicated by the @author tags.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.keycloak.models.authorization.infinispan;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.infinispan.Cache;
|
|
||||||
import org.keycloak.authorization.model.ResourceServer;
|
|
||||||
import org.keycloak.cluster.ClusterProvider;
|
|
||||||
import org.keycloak.models.KeycloakSession;
|
|
||||||
import org.keycloak.models.authorization.infinispan.events.AuthorizationInvalidationEvent;
|
|
||||||
import org.keycloak.models.authorization.infinispan.events.ResourceServerRemovedEvent;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
|
||||||
*/
|
|
||||||
public class StoreFactoryCacheManager {
|
|
||||||
|
|
||||||
private static final String AUTHORIZATION_UPDATE_TASK_KEY = "authorization-update";
|
|
||||||
|
|
||||||
private final Cache<String, Map<String, List<Object>>> cache;
|
|
||||||
|
|
||||||
StoreFactoryCacheManager(Cache<String, Map<String, List<Object>>> cache) {
|
|
||||||
this.cache = cache;
|
|
||||||
}
|
|
||||||
|
|
||||||
void invalidate(AuthorizationInvalidationEvent event) {
|
|
||||||
if (event instanceof ResourceServerRemovedEvent) {
|
|
||||||
cache.remove(event.getId());
|
|
||||||
cache.remove(ResourceServerRemovedEvent.class.cast(event).getClientId());
|
|
||||||
} else {
|
|
||||||
Map<String, List<Object>> resolveResourceServerCache = resolveResourceServerCache(event.getId());
|
|
||||||
|
|
||||||
for (String key : event.getInvalidations()) {
|
|
||||||
resolveResourceServerCache.remove(key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void invalidate(KeycloakSession session, String resourceServerId, Set<String> invalidations) {
|
|
||||||
getClusterProvider(session).notify(AUTHORIZATION_UPDATE_TASK_KEY, new AuthorizationInvalidationEvent(resourceServerId, invalidations), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, List<Object>> resolveResourceServerCache(String id) {
|
|
||||||
return cache.computeIfAbsent(id, key -> new HashMap<>());
|
|
||||||
}
|
|
||||||
|
|
||||||
void removeAll(KeycloakSession session, ResourceServer id) {
|
|
||||||
getClusterProvider(session).notify(AUTHORIZATION_UPDATE_TASK_KEY, new ResourceServerRemovedEvent(id.getId(), id.getClientId()), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private ClusterProvider getClusterProvider(KeycloakSession session) {
|
|
||||||
return session.getProvider(ClusterProvider.class);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,44 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
* and other contributors as indicated by the @author tags.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.keycloak.models.authorization.infinispan.events;
|
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.keycloak.models.cache.infinispan.events.InvalidationEvent;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
|
||||||
*/
|
|
||||||
public class AuthorizationInvalidationEvent extends InvalidationEvent {
|
|
||||||
|
|
||||||
private final String resourceServerId;
|
|
||||||
private Set<String> invalidations;
|
|
||||||
|
|
||||||
public AuthorizationInvalidationEvent(String resourceServerId, Set<String> invalidations) {
|
|
||||||
this.resourceServerId = resourceServerId;
|
|
||||||
this.invalidations = invalidations;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Set<String> getInvalidations() {
|
|
||||||
return invalidations;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getId() {
|
|
||||||
return resourceServerId;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -215,7 +215,7 @@ public abstract class CacheManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected void invalidationEventReceived(InvalidationEvent event) {
|
public void invalidationEventReceived(InvalidationEvent event) {
|
||||||
Set<String> invalidations = new HashSet<>();
|
Set<String> invalidations = new HashSet<>();
|
||||||
|
|
||||||
addInvalidationsFromEvent(event, invalidations);
|
addInvalidationsFromEvent(event, invalidations);
|
||||||
|
|
|
@ -0,0 +1,102 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||||
|
* and other contributors as indicated by the @author tags.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.keycloak.models.cache.infinispan.authorization;
|
||||||
|
|
||||||
|
import org.infinispan.Cache;
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
|
import org.keycloak.Config;
|
||||||
|
import org.keycloak.authorization.AuthorizationProvider;
|
||||||
|
import org.keycloak.cluster.ClusterEvent;
|
||||||
|
import org.keycloak.cluster.ClusterProvider;
|
||||||
|
import org.keycloak.connections.infinispan.InfinispanConnectionProvider;
|
||||||
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
import org.keycloak.models.KeycloakSessionFactory;
|
||||||
|
import org.keycloak.models.cache.CacheRealmProvider;
|
||||||
|
import org.keycloak.models.cache.CacheRealmProviderFactory;
|
||||||
|
import org.keycloak.models.cache.authorization.CachedStoreFactoryProvider;
|
||||||
|
import org.keycloak.models.cache.authorization.CachedStoreProviderFactory;
|
||||||
|
import org.keycloak.models.cache.infinispan.RealmCacheManager;
|
||||||
|
import org.keycloak.models.cache.infinispan.RealmCacheSession;
|
||||||
|
import org.keycloak.models.cache.infinispan.entities.Revisioned;
|
||||||
|
import org.keycloak.models.cache.infinispan.events.InvalidationEvent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||||
|
*/
|
||||||
|
public class InfinispanCacheStoreFactoryProviderFactory implements CachedStoreProviderFactory {
|
||||||
|
|
||||||
|
private static final Logger log = Logger.getLogger(InfinispanCacheStoreFactoryProviderFactory.class);
|
||||||
|
public static final String AUTHORIZATION_CLEAR_CACHE_EVENTS = "AUTHORIZATION_CLEAR_CACHE_EVENTS";
|
||||||
|
|
||||||
|
protected volatile StoreFactoryCacheManager storeCache;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CachedStoreFactoryProvider create(KeycloakSession session) {
|
||||||
|
lazyInit(session);
|
||||||
|
return new StoreFactoryCacheSession(storeCache, session);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void lazyInit(KeycloakSession session) {
|
||||||
|
if (storeCache == null) {
|
||||||
|
synchronized (this) {
|
||||||
|
if (storeCache == null) {
|
||||||
|
Cache<String, Revisioned> cache = session.getProvider(InfinispanConnectionProvider.class).getCache(InfinispanConnectionProvider.AUTHORIZATION_CACHE_NAME);
|
||||||
|
Cache<String, Long> revisions = session.getProvider(InfinispanConnectionProvider.class).getCache(InfinispanConnectionProvider.AUTHORIZATION_REVISIONS_CACHE_NAME);
|
||||||
|
storeCache = new StoreFactoryCacheManager(cache, revisions);
|
||||||
|
|
||||||
|
ClusterProvider cluster = session.getProvider(ClusterProvider.class);
|
||||||
|
cluster.registerListener(ClusterProvider.ALL, (ClusterEvent event) -> {
|
||||||
|
|
||||||
|
if (event instanceof InvalidationEvent) {
|
||||||
|
InvalidationEvent invalidationEvent = (InvalidationEvent) event;
|
||||||
|
storeCache.invalidationEventReceived(invalidationEvent);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
cluster.registerListener(AUTHORIZATION_CLEAR_CACHE_EVENTS, (ClusterEvent event) -> {
|
||||||
|
|
||||||
|
storeCache.clear();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
log.debug("Registered cluster listeners");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(Config.Scope config) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void postInit(KeycloakSessionFactory factory) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return "default";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
280
model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/authorization/PolicyAdapter.java
vendored
Normal file
280
model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/authorization/PolicyAdapter.java
vendored
Normal file
|
@ -0,0 +1,280 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||||
|
* and other contributors as indicated by the @author tags.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.keycloak.models.cache.infinispan.authorization;
|
||||||
|
|
||||||
|
import org.keycloak.authorization.model.CachedModel;
|
||||||
|
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.models.cache.infinispan.authorization.entities.CachedPolicy;
|
||||||
|
import org.keycloak.representations.idm.authorization.DecisionStrategy;
|
||||||
|
import org.keycloak.representations.idm.authorization.Logic;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class PolicyAdapter implements Policy, CachedModel<Policy> {
|
||||||
|
protected CachedPolicy cached;
|
||||||
|
protected StoreFactoryCacheSession cacheSession;
|
||||||
|
protected Policy updated;
|
||||||
|
|
||||||
|
public PolicyAdapter(CachedPolicy cached, StoreFactoryCacheSession cacheSession) {
|
||||||
|
this.cached = cached;
|
||||||
|
this.cacheSession = cacheSession;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Policy getDelegateForUpdate() {
|
||||||
|
if (updated == null) {
|
||||||
|
cacheSession.registerPolicyInvalidation(cached.getId(), cached.getName(), cached.getResourceServerId());
|
||||||
|
updated = cacheSession.getPolicyStoreDelegate().findById(cached.getId(), cached.getResourceServerId());
|
||||||
|
if (updated == null) throw new IllegalStateException("Not found in database");
|
||||||
|
}
|
||||||
|
return updated;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean invalidated;
|
||||||
|
|
||||||
|
protected void invalidateFlag() {
|
||||||
|
invalidated = true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void invalidate() {
|
||||||
|
invalidated = true;
|
||||||
|
getDelegateForUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getCacheTimestamp() {
|
||||||
|
return cached.getCacheTimestamp();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isUpdated() {
|
||||||
|
if (updated != null) return true;
|
||||||
|
if (!invalidated) return false;
|
||||||
|
updated = cacheSession.getPolicyStoreDelegate().findById(cached.getId(), cached.getResourceServerId());
|
||||||
|
if (updated == null) throw new IllegalStateException("Not found in database");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
if (isUpdated()) return updated.getId();
|
||||||
|
return cached.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
if (isUpdated()) return updated.getName();
|
||||||
|
return cached.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setName(String name) {
|
||||||
|
getDelegateForUpdate();
|
||||||
|
updated.setName(name);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResourceServer getResourceServer() {
|
||||||
|
return cacheSession.getResourceServerStore().findById(cached.getResourceServerId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getType() {
|
||||||
|
if (isUpdated()) return updated.getType();
|
||||||
|
return cached.getType();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DecisionStrategy getDecisionStrategy() {
|
||||||
|
if (isUpdated()) return updated.getDecisionStrategy();
|
||||||
|
return cached.getDecisionStrategy();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setDecisionStrategy(DecisionStrategy decisionStrategy) {
|
||||||
|
getDelegateForUpdate();
|
||||||
|
updated.setDecisionStrategy(decisionStrategy);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Logic getLogic() {
|
||||||
|
if (isUpdated()) return updated.getLogic();
|
||||||
|
return cached.getLogic();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setLogic(Logic logic) {
|
||||||
|
getDelegateForUpdate();
|
||||||
|
updated.setLogic(logic);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> getConfig() {
|
||||||
|
if (isUpdated()) return updated.getConfig();
|
||||||
|
return cached.getConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setConfig(Map<String, String> config) {
|
||||||
|
getDelegateForUpdate();
|
||||||
|
updated.setConfig(config);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeConfig(String name) {
|
||||||
|
getDelegateForUpdate();
|
||||||
|
updated.removeConfig(name);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void putConfig(String name, String value) {
|
||||||
|
getDelegateForUpdate();
|
||||||
|
updated.putConfig(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDescription() {
|
||||||
|
if (isUpdated()) return updated.getDescription();
|
||||||
|
return cached.getDescription();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setDescription(String description) {
|
||||||
|
getDelegateForUpdate();
|
||||||
|
updated.setDescription(description);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Set<Policy> associatedPolicies;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<Policy> getAssociatedPolicies() {
|
||||||
|
if (isUpdated()) return updated.getAssociatedPolicies();
|
||||||
|
if (associatedPolicies != null) return associatedPolicies;
|
||||||
|
associatedPolicies = new HashSet<>();
|
||||||
|
for (String scopeId : cached.getAssociatedPoliciesIds()) {
|
||||||
|
associatedPolicies.add(cacheSession.getPolicyStore().findById(scopeId, cached.getResourceServerId()));
|
||||||
|
}
|
||||||
|
associatedPolicies = Collections.unmodifiableSet(associatedPolicies);
|
||||||
|
return associatedPolicies;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Set<Resource> resources;
|
||||||
|
@Override
|
||||||
|
public Set<Resource> getResources() {
|
||||||
|
if (isUpdated()) return updated.getResources();
|
||||||
|
if (resources != null) return resources;
|
||||||
|
resources = new HashSet<>();
|
||||||
|
for (String resourceId : cached.getResourcesIds()) {
|
||||||
|
resources.add(cacheSession.getResourceStore().findById(resourceId, cached.getResourceServerId()));
|
||||||
|
}
|
||||||
|
resources = Collections.unmodifiableSet(resources);
|
||||||
|
return resources;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addScope(Scope scope) {
|
||||||
|
getDelegateForUpdate();
|
||||||
|
updated.addScope(scope);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeScope(Scope scope) {
|
||||||
|
getDelegateForUpdate();
|
||||||
|
updated.removeScope(scope);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addAssociatedPolicy(Policy associatedPolicy) {
|
||||||
|
getDelegateForUpdate();
|
||||||
|
updated.addAssociatedPolicy(associatedPolicy);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeAssociatedPolicy(Policy associatedPolicy) {
|
||||||
|
getDelegateForUpdate();
|
||||||
|
updated.removeAssociatedPolicy(associatedPolicy);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addResource(Resource resource) {
|
||||||
|
getDelegateForUpdate();
|
||||||
|
updated.addResource(resource);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeResource(Resource resource) {
|
||||||
|
getDelegateForUpdate();
|
||||||
|
updated.removeResource(resource);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Set<Scope> scopes;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<Scope> getScopes() {
|
||||||
|
if (isUpdated()) return updated.getScopes();
|
||||||
|
if (scopes != null) return scopes;
|
||||||
|
scopes = new HashSet<>();
|
||||||
|
for (String scopeId : cached.getScopesIds()) {
|
||||||
|
scopes.add(cacheSession.getScopeStore().findById(scopeId, cached.getResourceServerId()));
|
||||||
|
}
|
||||||
|
scopes = Collections.unmodifiableSet(scopes);
|
||||||
|
return scopes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || !(o instanceof Policy)) return false;
|
||||||
|
|
||||||
|
Policy that = (Policy) o;
|
||||||
|
return that.getId().equals(getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return getId().hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,184 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||||
|
* and other contributors as indicated by the @author tags.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.keycloak.models.cache.infinispan.authorization;
|
||||||
|
|
||||||
|
import org.keycloak.authorization.model.CachedModel;
|
||||||
|
import org.keycloak.authorization.model.Resource;
|
||||||
|
import org.keycloak.authorization.model.ResourceServer;
|
||||||
|
import org.keycloak.authorization.model.Scope;
|
||||||
|
import org.keycloak.models.cache.infinispan.authorization.entities.CachedResource;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class ResourceAdapter implements Resource, CachedModel<Resource> {
|
||||||
|
protected CachedResource cached;
|
||||||
|
protected StoreFactoryCacheSession cacheSession;
|
||||||
|
protected Resource updated;
|
||||||
|
|
||||||
|
public ResourceAdapter(CachedResource cached, StoreFactoryCacheSession cacheSession) {
|
||||||
|
this.cached = cached;
|
||||||
|
this.cacheSession = cacheSession;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Resource getDelegateForUpdate() {
|
||||||
|
if (updated == null) {
|
||||||
|
cacheSession.registerResourceInvalidation(cached.getId(), cached.getName(), cached.getResourceServerId());
|
||||||
|
updated = cacheSession.getResourceStoreDelegate().findById(cached.getId(), cached.getResourceServerId());
|
||||||
|
if (updated == null) throw new IllegalStateException("Not found in database");
|
||||||
|
}
|
||||||
|
return updated;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean invalidated;
|
||||||
|
|
||||||
|
protected void invalidateFlag() {
|
||||||
|
invalidated = true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void invalidate() {
|
||||||
|
invalidated = true;
|
||||||
|
getDelegateForUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getCacheTimestamp() {
|
||||||
|
return cached.getCacheTimestamp();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isUpdated() {
|
||||||
|
if (updated != null) return true;
|
||||||
|
if (!invalidated) return false;
|
||||||
|
updated = cacheSession.getResourceStoreDelegate().findById(cached.getId(), cached.getResourceServerId());
|
||||||
|
if (updated == null) throw new IllegalStateException("Not found in database");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
if (isUpdated()) return updated.getId();
|
||||||
|
return cached.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
if (isUpdated()) return updated.getName();
|
||||||
|
return cached.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setName(String name) {
|
||||||
|
getDelegateForUpdate();
|
||||||
|
updated.setName(name);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getIconUri() {
|
||||||
|
if (isUpdated()) return updated.getIconUri();
|
||||||
|
return cached.getIconUri();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setIconUri(String iconUri) {
|
||||||
|
getDelegateForUpdate();
|
||||||
|
updated.setIconUri(iconUri);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResourceServer getResourceServer() {
|
||||||
|
return cacheSession.getResourceServerStore().findById(cached.getResourceServerId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUri() {
|
||||||
|
if (isUpdated()) return updated.getUri();
|
||||||
|
return cached.getUri();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setUri(String uri) {
|
||||||
|
getDelegateForUpdate();
|
||||||
|
updated.setUri(uri);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getType() {
|
||||||
|
if (isUpdated()) return updated.getType();
|
||||||
|
return cached.getType();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setType(String type) {
|
||||||
|
getDelegateForUpdate();
|
||||||
|
updated.setType(type);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List<Scope> scopes;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Scope> getScopes() {
|
||||||
|
if (isUpdated()) return updated.getScopes();
|
||||||
|
if (scopes != null) return scopes;
|
||||||
|
scopes = new LinkedList<>();
|
||||||
|
for (String scopeId : cached.getScopesIds()) {
|
||||||
|
scopes.add(cacheSession.getScopeStore().findById(scopeId, cached.getResourceServerId()));
|
||||||
|
}
|
||||||
|
scopes = Collections.unmodifiableList(scopes);
|
||||||
|
return scopes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getOwner() {
|
||||||
|
if (isUpdated()) return updated.getOwner();
|
||||||
|
return cached.getOwner();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateScopes(Set<Scope> scopes) {
|
||||||
|
getDelegateForUpdate();
|
||||||
|
updated.updateScopes(scopes);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || !(o instanceof Resource)) return false;
|
||||||
|
|
||||||
|
Resource that = (Resource) o;
|
||||||
|
return that.getId().equals(getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return getId().hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,127 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||||
|
* and other contributors as indicated by the @author tags.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.keycloak.models.cache.infinispan.authorization;
|
||||||
|
|
||||||
|
import org.keycloak.authorization.model.CachedModel;
|
||||||
|
import org.keycloak.authorization.model.ResourceServer;
|
||||||
|
import org.keycloak.models.cache.infinispan.authorization.entities.CachedResourceServer;
|
||||||
|
import org.keycloak.representations.idm.authorization.PolicyEnforcementMode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class ResourceServerAdapter implements ResourceServer, CachedModel<ResourceServer> {
|
||||||
|
protected CachedResourceServer cached;
|
||||||
|
protected StoreFactoryCacheSession cacheSession;
|
||||||
|
protected ResourceServer updated;
|
||||||
|
|
||||||
|
public ResourceServerAdapter(CachedResourceServer cached, StoreFactoryCacheSession cacheSession) {
|
||||||
|
this.cached = cached;
|
||||||
|
this.cacheSession = cacheSession;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResourceServer getDelegateForUpdate() {
|
||||||
|
if (updated == null) {
|
||||||
|
cacheSession.registerResourceServerInvalidation(cached.getId(), cached.getClientId());
|
||||||
|
updated = cacheSession.getResourceServerStoreDelegate().findById(cached.getId());
|
||||||
|
if (updated == null) throw new IllegalStateException("Not found in database");
|
||||||
|
}
|
||||||
|
return updated;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean invalidated;
|
||||||
|
|
||||||
|
protected void invalidateFlag() {
|
||||||
|
invalidated = true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void invalidate() {
|
||||||
|
invalidated = true;
|
||||||
|
getDelegateForUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getCacheTimestamp() {
|
||||||
|
return cached.getCacheTimestamp();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isUpdated() {
|
||||||
|
if (updated != null) return true;
|
||||||
|
if (!invalidated) return false;
|
||||||
|
updated = cacheSession.getResourceServerStoreDelegate().findById(cached.getId());
|
||||||
|
if (updated == null) throw new IllegalStateException("Not found in database");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
if (isUpdated()) return updated.getId();
|
||||||
|
return cached.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getClientId() {
|
||||||
|
if (isUpdated()) return updated.getClientId();
|
||||||
|
return cached.getClientId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAllowRemoteResourceManagement() {
|
||||||
|
if (isUpdated()) return updated.isAllowRemoteResourceManagement();
|
||||||
|
return cached.isAllowRemoteResourceManagement();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAllowRemoteResourceManagement(boolean allowRemoteResourceManagement) {
|
||||||
|
getDelegateForUpdate();
|
||||||
|
updated.setAllowRemoteResourceManagement(allowRemoteResourceManagement);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PolicyEnforcementMode getPolicyEnforcementMode() {
|
||||||
|
if (isUpdated()) return updated.getPolicyEnforcementMode();
|
||||||
|
return cached.getPolicyEnforcementMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPolicyEnforcementMode(PolicyEnforcementMode enforcementMode) {
|
||||||
|
getDelegateForUpdate();
|
||||||
|
updated.setPolicyEnforcementMode(enforcementMode);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || !(o instanceof ResourceServer)) return false;
|
||||||
|
|
||||||
|
ResourceServer that = (ResourceServer) o;
|
||||||
|
return that.getId().equals(getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return getId().hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
127
model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/authorization/ScopeAdapter.java
vendored
Normal file
127
model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/authorization/ScopeAdapter.java
vendored
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||||
|
* and other contributors as indicated by the @author tags.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.keycloak.models.cache.infinispan.authorization;
|
||||||
|
|
||||||
|
import org.keycloak.authorization.model.CachedModel;
|
||||||
|
import org.keycloak.authorization.model.ResourceServer;
|
||||||
|
import org.keycloak.authorization.model.Scope;
|
||||||
|
import org.keycloak.models.cache.infinispan.authorization.entities.CachedScope;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class ScopeAdapter implements Scope, CachedModel<Scope> {
|
||||||
|
protected CachedScope cached;
|
||||||
|
protected StoreFactoryCacheSession cacheSession;
|
||||||
|
protected Scope updated;
|
||||||
|
|
||||||
|
public ScopeAdapter(CachedScope cached, StoreFactoryCacheSession cacheSession) {
|
||||||
|
this.cached = cached;
|
||||||
|
this.cacheSession = cacheSession;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Scope getDelegateForUpdate() {
|
||||||
|
if (updated == null) {
|
||||||
|
cacheSession.registerScopeInvalidation(cached.getId(), cached.getName(), cached.getResourceServerId());
|
||||||
|
updated = cacheSession.getScopeStoreDelegate().findById(cached.getId(), cached.getResourceServerId());
|
||||||
|
if (updated == null) throw new IllegalStateException("Not found in database");
|
||||||
|
}
|
||||||
|
return updated;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean invalidated;
|
||||||
|
|
||||||
|
protected void invalidateFlag() {
|
||||||
|
invalidated = true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void invalidate() {
|
||||||
|
invalidated = true;
|
||||||
|
getDelegateForUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getCacheTimestamp() {
|
||||||
|
return cached.getCacheTimestamp();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isUpdated() {
|
||||||
|
if (updated != null) return true;
|
||||||
|
if (!invalidated) return false;
|
||||||
|
updated = cacheSession.getScopeStoreDelegate().findById(cached.getId(), cached.getResourceServerId());
|
||||||
|
if (updated == null) throw new IllegalStateException("Not found in database");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
if (isUpdated()) return updated.getId();
|
||||||
|
return cached.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
if (isUpdated()) return updated.getName();
|
||||||
|
return cached.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setName(String name) {
|
||||||
|
getDelegateForUpdate();
|
||||||
|
updated.setName(name);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getIconUri() {
|
||||||
|
if (isUpdated()) return updated.getIconUri();
|
||||||
|
return cached.getIconUri();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setIconUri(String iconUri) {
|
||||||
|
getDelegateForUpdate();
|
||||||
|
updated.setIconUri(iconUri);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResourceServer getResourceServer() {
|
||||||
|
return cacheSession.getResourceServerStore().findById(cached.getResourceServerId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || !(o instanceof Scope)) return false;
|
||||||
|
|
||||||
|
Scope that = (Scope) o;
|
||||||
|
return that.getId().equals(getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return getId().hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,93 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||||
|
* and other contributors as indicated by the @author tags.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.keycloak.models.cache.infinispan.authorization;
|
||||||
|
|
||||||
|
import org.infinispan.Cache;
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
|
import org.keycloak.models.cache.infinispan.CacheManager;
|
||||||
|
import org.keycloak.models.cache.infinispan.RealmCacheManager;
|
||||||
|
import org.keycloak.models.cache.infinispan.authorization.events.AuthorizationCacheInvalidationEvent;
|
||||||
|
import org.keycloak.models.cache.infinispan.authorization.stream.InResourceServerPredicate;
|
||||||
|
import org.keycloak.models.cache.infinispan.entities.Revisioned;
|
||||||
|
import org.keycloak.models.cache.infinispan.events.InvalidationEvent;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class StoreFactoryCacheManager extends CacheManager {
|
||||||
|
private static final Logger logger = Logger.getLogger(RealmCacheManager.class);
|
||||||
|
|
||||||
|
public StoreFactoryCacheManager(Cache<String, Revisioned> cache, Cache<String, Long> revisions) {
|
||||||
|
super(cache, revisions);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
protected Logger getLogger() {
|
||||||
|
return logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addInvalidationsFromEvent(InvalidationEvent event, Set<String> invalidations) {
|
||||||
|
if (event instanceof AuthorizationCacheInvalidationEvent) {
|
||||||
|
invalidations.add(event.getId());
|
||||||
|
|
||||||
|
((AuthorizationCacheInvalidationEvent) event).addInvalidations(this, invalidations);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resourceServerUpdated(String id, String clientId, Set<String> invalidations) {
|
||||||
|
invalidations.add(id);
|
||||||
|
invalidations.add(StoreFactoryCacheSession.getResourceServerByClientCacheKey(clientId));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resourceServerRemoval(String id, String name, Set<String> invalidations) {
|
||||||
|
resourceServerUpdated(id, name, invalidations);
|
||||||
|
|
||||||
|
addInvalidations(InResourceServerPredicate.create().resourceServer(id), invalidations);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void scopeUpdated(String id, String name, String serverId, Set<String> invalidations) {
|
||||||
|
invalidations.add(id);
|
||||||
|
invalidations.add(StoreFactoryCacheSession.getScopeByNameCacheKey(name, serverId));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void scopeRemoval(String id, String name, String serverId, Set<String> invalidations) {
|
||||||
|
scopeUpdated(id, name, serverId, invalidations);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resourceUpdated(String id, String name, String serverId, Set<String> invalidations) {
|
||||||
|
invalidations.add(id);
|
||||||
|
invalidations.add(StoreFactoryCacheSession.getResourceByNameCacheKey(name, serverId));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resourceRemoval(String id, String name, String serverId, Set<String> invalidations) {
|
||||||
|
resourceUpdated(id, name, serverId, invalidations);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void policyUpdated(String id, String name, String serverId, Set<String> invalidations) {
|
||||||
|
invalidations.add(id);
|
||||||
|
invalidations.add(StoreFactoryCacheSession.getPolicyByNameCacheKey(name, serverId));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void policyRemoval(String id, String name, String serverId, Set<String> invalidations) {
|
||||||
|
policyUpdated(id, name, serverId, invalidations);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,667 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||||
|
* and other contributors as indicated by the @author tags.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.keycloak.models.cache.infinispan.authorization;
|
||||||
|
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
|
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.store.PolicyStore;
|
||||||
|
import org.keycloak.authorization.store.ResourceServerStore;
|
||||||
|
import org.keycloak.authorization.store.ResourceStore;
|
||||||
|
import org.keycloak.authorization.store.ScopeStore;
|
||||||
|
import org.keycloak.authorization.store.StoreFactory;
|
||||||
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
import org.keycloak.models.KeycloakTransaction;
|
||||||
|
import org.keycloak.models.cache.authorization.CachedStoreFactoryProvider;
|
||||||
|
import org.keycloak.models.cache.infinispan.authorization.entities.CachedPolicy;
|
||||||
|
import org.keycloak.models.cache.infinispan.authorization.entities.CachedResource;
|
||||||
|
import org.keycloak.models.cache.infinispan.authorization.entities.CachedResourceServer;
|
||||||
|
import org.keycloak.models.cache.infinispan.authorization.entities.CachedScope;
|
||||||
|
import org.keycloak.models.cache.infinispan.authorization.entities.PolicyListQuery;
|
||||||
|
import org.keycloak.models.cache.infinispan.authorization.entities.ResourceListQuery;
|
||||||
|
import org.keycloak.models.cache.infinispan.authorization.entities.ResourceServerListQuery;
|
||||||
|
import org.keycloak.models.cache.infinispan.authorization.entities.ScopeListQuery;
|
||||||
|
import org.keycloak.models.cache.infinispan.authorization.events.PolicyRemovedEvent;
|
||||||
|
import org.keycloak.models.cache.infinispan.authorization.events.PolicyUpdatedEvent;
|
||||||
|
import org.keycloak.models.cache.infinispan.authorization.events.ResourceRemovedEvent;
|
||||||
|
import org.keycloak.models.cache.infinispan.authorization.events.ResourceServerRemovedEvent;
|
||||||
|
import org.keycloak.models.cache.infinispan.authorization.events.ResourceServerUpdatedEvent;
|
||||||
|
import org.keycloak.models.cache.infinispan.authorization.events.ResourceUpdatedEvent;
|
||||||
|
import org.keycloak.models.cache.infinispan.authorization.events.ScopeRemovedEvent;
|
||||||
|
import org.keycloak.models.cache.infinispan.authorization.events.ScopeUpdatedEvent;
|
||||||
|
import org.keycloak.models.cache.infinispan.events.InvalidationEvent;
|
||||||
|
import org.keycloak.representations.idm.authorization.AbstractPolicyRepresentation;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class StoreFactoryCacheSession implements CachedStoreFactoryProvider {
|
||||||
|
protected static final Logger logger = Logger.getLogger(StoreFactoryCacheSession.class);
|
||||||
|
|
||||||
|
protected StoreFactoryCacheManager cache;
|
||||||
|
protected boolean transactionActive;
|
||||||
|
protected boolean setRollbackOnly;
|
||||||
|
|
||||||
|
protected Map<String, ResourceServerAdapter> managedResourceServers = new HashMap<>();
|
||||||
|
protected Map<String, ScopeAdapter> managedScopes = new HashMap<>();
|
||||||
|
protected Map<String, ResourceAdapter> managedResources = new HashMap<>();
|
||||||
|
protected Map<String, PolicyAdapter> managedPolicies = new HashMap<>();
|
||||||
|
protected Set<String> invalidations = new HashSet<>();
|
||||||
|
protected Set<InvalidationEvent> invalidationEvents = new HashSet<>(); // Events to be sent across cluster
|
||||||
|
|
||||||
|
protected boolean clearAll;
|
||||||
|
protected final long startupRevision;
|
||||||
|
protected StoreFactory delegate;
|
||||||
|
protected KeycloakSession session;
|
||||||
|
protected ResourceServerCache resourceServerCache;
|
||||||
|
protected ScopeCache scopeCache;
|
||||||
|
protected ResourceCache resourceCache;
|
||||||
|
protected PolicyCache policyCache;
|
||||||
|
|
||||||
|
public StoreFactoryCacheSession(StoreFactoryCacheManager cache, KeycloakSession session) {
|
||||||
|
this.cache = cache;
|
||||||
|
this.startupRevision = cache.getCurrentCounter();
|
||||||
|
this.session = session;
|
||||||
|
this.resourceServerCache = new ResourceServerCache();
|
||||||
|
this.scopeCache = new ScopeCache();
|
||||||
|
this.resourceCache = new ResourceCache();
|
||||||
|
this.policyCache = new PolicyCache();
|
||||||
|
session.getTransactionManager().enlistPrepare(getPrepareTransaction());
|
||||||
|
session.getTransactionManager().enlistAfterCompletion(getAfterTransaction());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResourceServerStore getResourceServerStore() {
|
||||||
|
return resourceServerCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ScopeStore getScopeStore() {
|
||||||
|
return scopeCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResourceStore getResourceStore() {
|
||||||
|
return resourceCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PolicyStore getPolicyStore() {
|
||||||
|
return policyCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() {
|
||||||
|
}
|
||||||
|
|
||||||
|
private KeycloakTransaction getPrepareTransaction() {
|
||||||
|
return new KeycloakTransaction() {
|
||||||
|
@Override
|
||||||
|
public void begin() {
|
||||||
|
transactionActive = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void commit() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void rollback() {
|
||||||
|
setRollbackOnly = true;
|
||||||
|
transactionActive = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setRollbackOnly() {
|
||||||
|
setRollbackOnly = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getRollbackOnly() {
|
||||||
|
return setRollbackOnly;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isActive() {
|
||||||
|
return transactionActive;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private KeycloakTransaction getAfterTransaction() {
|
||||||
|
return new KeycloakTransaction() {
|
||||||
|
@Override
|
||||||
|
public void begin() {
|
||||||
|
transactionActive = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void commit() {
|
||||||
|
try {
|
||||||
|
if (getDelegate() == null) return;
|
||||||
|
if (clearAll) {
|
||||||
|
cache.clear();
|
||||||
|
}
|
||||||
|
runInvalidations();
|
||||||
|
transactionActive = false;
|
||||||
|
} finally {
|
||||||
|
cache.endRevisionBatch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void rollback() {
|
||||||
|
try {
|
||||||
|
setRollbackOnly = true;
|
||||||
|
runInvalidations();
|
||||||
|
transactionActive = false;
|
||||||
|
} finally {
|
||||||
|
cache.endRevisionBatch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setRollbackOnly() {
|
||||||
|
setRollbackOnly = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getRollbackOnly() {
|
||||||
|
return setRollbackOnly;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isActive() {
|
||||||
|
return transactionActive;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void runInvalidations() {
|
||||||
|
for (String id : invalidations) {
|
||||||
|
cache.invalidateObject(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
cache.sendInvalidationEvents(session, invalidationEvents);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public long getStartupRevision() {
|
||||||
|
return startupRevision;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isInvalid(String id) {
|
||||||
|
return invalidations.contains(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void registerResourceServerInvalidation(String id, String clientId) {
|
||||||
|
cache.resourceServerUpdated(id, clientId, invalidations);
|
||||||
|
ResourceServerAdapter adapter = managedResourceServers.get(id);
|
||||||
|
if (adapter != null) adapter.invalidateFlag();
|
||||||
|
|
||||||
|
invalidationEvents.add(ResourceServerUpdatedEvent.create(id, clientId));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void registerScopeInvalidation(String id, String name, String serverId) {
|
||||||
|
cache.scopeUpdated(id, name, serverId, invalidations);
|
||||||
|
ScopeAdapter adapter = managedScopes.get(id);
|
||||||
|
if (adapter != null) adapter.invalidateFlag();
|
||||||
|
|
||||||
|
invalidationEvents.add(ScopeUpdatedEvent.create(id, name, serverId));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void registerResourceInvalidation(String id, String name, String serverId) {
|
||||||
|
cache.resourceUpdated(id, name, serverId, invalidations);
|
||||||
|
ResourceAdapter adapter = managedResources.get(id);
|
||||||
|
if (adapter != null) adapter.invalidateFlag();
|
||||||
|
|
||||||
|
invalidationEvents.add(ResourceUpdatedEvent.create(id, name, serverId));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void registerPolicyInvalidation(String id, String name, String serverId) {
|
||||||
|
cache.policyUpdated(id, name, serverId, invalidations);
|
||||||
|
PolicyAdapter adapter = managedPolicies.get(id);
|
||||||
|
if (adapter != null) adapter.invalidateFlag();
|
||||||
|
|
||||||
|
invalidationEvents.add(PolicyUpdatedEvent.create(id, name, serverId));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResourceServerStore getResourceServerStoreDelegate() {
|
||||||
|
return getDelegate().getResourceServerStore();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ScopeStore getScopeStoreDelegate() {
|
||||||
|
return getDelegate().getScopeStore();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResourceStore getResourceStoreDelegate() {
|
||||||
|
return getDelegate().getResourceStore();
|
||||||
|
}
|
||||||
|
|
||||||
|
public PolicyStore getPolicyStoreDelegate() {
|
||||||
|
return getDelegate().getPolicyStore();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getResourceServerByClientCacheKey(String clientId) {
|
||||||
|
return "resource.server.client.id." + clientId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getScopeByNameCacheKey(String name, String serverId) {
|
||||||
|
return "scope.name." + name + "." + serverId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getResourceByNameCacheKey(String name, String serverId) {
|
||||||
|
return "resource.name." + name + "." + serverId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getPolicyByNameCacheKey(String name, String serverId) {
|
||||||
|
return "policy.name." + name + "." + serverId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StoreFactory getDelegate() {
|
||||||
|
if (delegate != null) return delegate;
|
||||||
|
delegate = session.getProvider(StoreFactory.class);
|
||||||
|
return delegate;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected class ResourceServerCache implements ResourceServerStore {
|
||||||
|
@Override
|
||||||
|
public ResourceServer create(String clientId) {
|
||||||
|
ResourceServer server = getResourceServerStoreDelegate().create(clientId);
|
||||||
|
registerResourceServerInvalidation(server.getId(), server.getClientId());
|
||||||
|
return server;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void delete(String id) {
|
||||||
|
if (id == null) return;
|
||||||
|
ResourceServer server = findById(id);
|
||||||
|
if (server == null) return;
|
||||||
|
|
||||||
|
cache.invalidateObject(id);
|
||||||
|
invalidationEvents.add(ResourceServerRemovedEvent.create(id, server.getClientId()));
|
||||||
|
cache.resourceServerRemoval(id, server.getClientId(), invalidations);
|
||||||
|
getResourceServerStoreDelegate().delete(id);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResourceServer findById(String id) {
|
||||||
|
if (id == null) return null;
|
||||||
|
CachedResourceServer cached = cache.get(id, CachedResourceServer.class);
|
||||||
|
if (cached != null) {
|
||||||
|
logger.tracev("by id cache hit: {0}", cached.getId());
|
||||||
|
}
|
||||||
|
boolean wasCached = false;
|
||||||
|
if (cached == null) {
|
||||||
|
Long loaded = cache.getCurrentRevision(id);
|
||||||
|
ResourceServer model = getResourceServerStoreDelegate().findById(id);
|
||||||
|
if (model == null) return null;
|
||||||
|
if (invalidations.contains(id)) return model;
|
||||||
|
cached = new CachedResourceServer(loaded, model);
|
||||||
|
cache.addRevisioned(cached, startupRevision);
|
||||||
|
wasCached =true;
|
||||||
|
} else if (invalidations.contains(id)) {
|
||||||
|
return getResourceServerStoreDelegate().findById(id);
|
||||||
|
} else if (managedResourceServers.containsKey(id)) {
|
||||||
|
return managedResourceServers.get(id);
|
||||||
|
}
|
||||||
|
ResourceServerAdapter adapter = new ResourceServerAdapter(cached, StoreFactoryCacheSession.this);
|
||||||
|
managedResourceServers.put(id, adapter);
|
||||||
|
return adapter;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResourceServer findByClient(String clientId) {
|
||||||
|
String cacheKey = getResourceServerByClientCacheKey(clientId);
|
||||||
|
ResourceServerListQuery query = cache.get(cacheKey, ResourceServerListQuery.class);
|
||||||
|
if (query != null) {
|
||||||
|
logger.tracev("ResourceServer by clientId cache hit: {0}", clientId);
|
||||||
|
}
|
||||||
|
if (query == null) {
|
||||||
|
Long loaded = cache.getCurrentRevision(cacheKey);
|
||||||
|
ResourceServer model = getResourceServerStoreDelegate().findByClient(clientId);
|
||||||
|
if (model == null) return null;
|
||||||
|
if (invalidations.contains(model.getId())) return model;
|
||||||
|
query = new ResourceServerListQuery(loaded, cacheKey, model.getId());
|
||||||
|
cache.addRevisioned(query, startupRevision);
|
||||||
|
return model;
|
||||||
|
} else if (invalidations.contains(cacheKey)) {
|
||||||
|
return getResourceServerStoreDelegate().findByClient(clientId);
|
||||||
|
} else {
|
||||||
|
String serverId = query.getResourceServers().iterator().next();
|
||||||
|
if (invalidations.contains(serverId)) {
|
||||||
|
return getResourceServerStoreDelegate().findByClient(clientId);
|
||||||
|
}
|
||||||
|
return findById(serverId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class ScopeCache implements ScopeStore {
|
||||||
|
@Override
|
||||||
|
public Scope create(String name, ResourceServer resourceServer) {
|
||||||
|
Scope scope = getScopeStoreDelegate().create(name, resourceServer);
|
||||||
|
registerScopeInvalidation(scope.getId(), scope.getName(), resourceServer.getId());
|
||||||
|
return scope;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void delete(String id) {
|
||||||
|
if (id == null) return;
|
||||||
|
Scope scope = findById(id, null);
|
||||||
|
if (scope == null) return;
|
||||||
|
|
||||||
|
cache.invalidateObject(id);
|
||||||
|
invalidationEvents.add(ScopeRemovedEvent.create(id, scope.getName(), scope.getResourceServer().getId()));
|
||||||
|
cache.scopeRemoval(id, scope.getName(), scope.getResourceServer().getId(), invalidations);
|
||||||
|
getScopeStoreDelegate().delete(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Scope findById(String id, String resourceServerId) {
|
||||||
|
if (id == null) return null;
|
||||||
|
CachedScope cached = cache.get(id, CachedScope.class);
|
||||||
|
if (cached != null) {
|
||||||
|
logger.tracev("by id cache hit: {0}", cached.getId());
|
||||||
|
}
|
||||||
|
boolean wasCached = false;
|
||||||
|
if (cached == null) {
|
||||||
|
Long loaded = cache.getCurrentRevision(id);
|
||||||
|
Scope model = getScopeStoreDelegate().findById(id, resourceServerId);
|
||||||
|
if (model == null) return null;
|
||||||
|
if (invalidations.contains(id)) return model;
|
||||||
|
cached = new CachedScope(loaded, model);
|
||||||
|
cache.addRevisioned(cached, startupRevision);
|
||||||
|
wasCached =true;
|
||||||
|
} else if (invalidations.contains(id)) {
|
||||||
|
return getScopeStoreDelegate().findById(id, resourceServerId);
|
||||||
|
} else if (managedScopes.containsKey(id)) {
|
||||||
|
return managedScopes.get(id);
|
||||||
|
}
|
||||||
|
ScopeAdapter adapter = new ScopeAdapter(cached, StoreFactoryCacheSession.this);
|
||||||
|
managedScopes.put(id, adapter);
|
||||||
|
return adapter;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Scope findByName(String name, String resourceServerId) {
|
||||||
|
if (name == null) return null;
|
||||||
|
String cacheKey = getScopeByNameCacheKey(name, resourceServerId);
|
||||||
|
ScopeListQuery query = cache.get(cacheKey, ScopeListQuery.class);
|
||||||
|
if (query != null) {
|
||||||
|
logger.tracev("scope by name cache hit: {0}", name);
|
||||||
|
}
|
||||||
|
if (query == null) {
|
||||||
|
Long loaded = cache.getCurrentRevision(cacheKey);
|
||||||
|
Scope model = getScopeStoreDelegate().findByName(name, resourceServerId);
|
||||||
|
if (model == null) return null;
|
||||||
|
if (invalidations.contains(model.getId())) return model;
|
||||||
|
query = new ScopeListQuery(loaded, cacheKey, model.getId(), resourceServerId);
|
||||||
|
cache.addRevisioned(query, startupRevision);
|
||||||
|
return model;
|
||||||
|
} else if (invalidations.contains(cacheKey)) {
|
||||||
|
return getScopeStoreDelegate().findByName(name, resourceServerId);
|
||||||
|
} else {
|
||||||
|
String id = query.getScopes().iterator().next();
|
||||||
|
if (invalidations.contains(id)) {
|
||||||
|
return getScopeStoreDelegate().findByName(name, resourceServerId);
|
||||||
|
}
|
||||||
|
return findById(id, query.getResourceServerId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Scope> findByResourceServer(String id) {
|
||||||
|
return getScopeStoreDelegate().findByResourceServer(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Scope> findByResourceServer(Map<String, String[]> attributes, String resourceServerId, int firstResult, int maxResult) {
|
||||||
|
return getScopeStoreDelegate().findByResourceServer(attributes, resourceServerId, firstResult, maxResult);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class ResourceCache implements ResourceStore {
|
||||||
|
@Override
|
||||||
|
public Resource create(String name, ResourceServer resourceServer, String owner) {
|
||||||
|
Resource resource = getResourceStoreDelegate().create(name, resourceServer, owner);
|
||||||
|
registerResourceInvalidation(resource.getId(), resource.getName(), resourceServer.getId());
|
||||||
|
return resource;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void delete(String id) {
|
||||||
|
if (id == null) return;
|
||||||
|
Resource resource = findById(id, null);
|
||||||
|
if (resource == null) return;
|
||||||
|
|
||||||
|
cache.invalidateObject(id);
|
||||||
|
invalidationEvents.add(ResourceRemovedEvent.create(id, resource.getName(), resource.getResourceServer().getId()));
|
||||||
|
cache.resourceRemoval(id, resource.getName(), resource.getResourceServer().getId(), invalidations);
|
||||||
|
getResourceStoreDelegate().delete(id);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Resource findById(String id, String resourceServerId) {
|
||||||
|
if (id == null) return null;
|
||||||
|
CachedResource cached = cache.get(id, CachedResource.class);
|
||||||
|
if (cached != null) {
|
||||||
|
logger.tracev("by id cache hit: {0}", cached.getId());
|
||||||
|
}
|
||||||
|
boolean wasCached = false;
|
||||||
|
if (cached == null) {
|
||||||
|
Long loaded = cache.getCurrentRevision(id);
|
||||||
|
Resource model = getResourceStoreDelegate().findById(id, resourceServerId);
|
||||||
|
if (model == null) return null;
|
||||||
|
if (invalidations.contains(id)) return model;
|
||||||
|
cached = new CachedResource(loaded, model);
|
||||||
|
cache.addRevisioned(cached, startupRevision);
|
||||||
|
wasCached =true;
|
||||||
|
} else if (invalidations.contains(id)) {
|
||||||
|
return getResourceStoreDelegate().findById(id, resourceServerId);
|
||||||
|
} else if (managedResources.containsKey(id)) {
|
||||||
|
return managedResources.get(id);
|
||||||
|
}
|
||||||
|
ResourceAdapter adapter = new ResourceAdapter(cached, StoreFactoryCacheSession.this);
|
||||||
|
managedResources.put(id, adapter);
|
||||||
|
return adapter;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Resource findByName(String name, String resourceServerId) {
|
||||||
|
if (name == null) return null;
|
||||||
|
String cacheKey = getResourceByNameCacheKey(name, resourceServerId);
|
||||||
|
ResourceListQuery query = cache.get(cacheKey, ResourceListQuery.class);
|
||||||
|
if (query != null) {
|
||||||
|
logger.tracev("resource by name cache hit: {0}", name);
|
||||||
|
}
|
||||||
|
if (query == null) {
|
||||||
|
Long loaded = cache.getCurrentRevision(cacheKey);
|
||||||
|
Resource model = getResourceStoreDelegate().findByName(name, resourceServerId);
|
||||||
|
if (model == null) return null;
|
||||||
|
if (invalidations.contains(model.getId())) return model;
|
||||||
|
query = new ResourceListQuery(loaded, cacheKey, model.getId(), resourceServerId);
|
||||||
|
cache.addRevisioned(query, startupRevision);
|
||||||
|
return model;
|
||||||
|
} else if (invalidations.contains(cacheKey)) {
|
||||||
|
return getResourceStoreDelegate().findByName(name, resourceServerId);
|
||||||
|
} else {
|
||||||
|
String id = query.getResources().iterator().next();
|
||||||
|
if (invalidations.contains(id)) {
|
||||||
|
return getResourceStoreDelegate().findByName(name, resourceServerId);
|
||||||
|
}
|
||||||
|
return findById(id, query.getResourceServerId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Resource> findByOwner(String ownerId, String resourceServerId) {
|
||||||
|
return getResourceStoreDelegate().findByOwner(ownerId, resourceServerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Resource> findByUri(String uri, String resourceServerId) {
|
||||||
|
return getResourceStoreDelegate().findByUri(uri, resourceServerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Resource> findByResourceServer(String resourceServerId) {
|
||||||
|
return getResourceStoreDelegate().findByResourceServer(resourceServerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Resource> findByResourceServer(Map<String, String[]> attributes, String resourceServerId, int firstResult, int maxResult) {
|
||||||
|
return getResourceStoreDelegate().findByResourceServer(attributes, resourceServerId, firstResult, maxResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Resource> findByScope(List<String> ids, String resourceServerId) {
|
||||||
|
return getResourceStoreDelegate().findByScope(ids, resourceServerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Resource> findByType(String type, String resourceServerId) {
|
||||||
|
return getResourceStoreDelegate().findByType(type, resourceServerId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class PolicyCache implements PolicyStore {
|
||||||
|
@Override
|
||||||
|
public Policy create(AbstractPolicyRepresentation representation, ResourceServer resourceServer) {
|
||||||
|
Policy resource = getPolicyStoreDelegate().create(representation, resourceServer);
|
||||||
|
registerPolicyInvalidation(resource.getId(), resource.getName(), resourceServer.getId());
|
||||||
|
return resource;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void delete(String id) {
|
||||||
|
if (id == null) return;
|
||||||
|
Policy policy = findById(id, null);
|
||||||
|
if (policy == null) return;
|
||||||
|
|
||||||
|
cache.invalidateObject(id);
|
||||||
|
invalidationEvents.add(PolicyRemovedEvent.create(id, policy.getName(), policy.getResourceServer().getId()));
|
||||||
|
cache.policyRemoval(id, policy.getName(), policy.getResourceServer().getId(), invalidations);
|
||||||
|
getPolicyStoreDelegate().delete(id);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Policy findById(String id, String resourceServerId) {
|
||||||
|
if (id == null) return null;
|
||||||
|
|
||||||
|
CachedPolicy cached = cache.get(id, CachedPolicy.class);
|
||||||
|
if (cached != null) {
|
||||||
|
logger.tracev("by id cache hit: {0}", cached.getId());
|
||||||
|
}
|
||||||
|
boolean wasCached = false;
|
||||||
|
if (cached == null) {
|
||||||
|
Long loaded = cache.getCurrentRevision(id);
|
||||||
|
Policy model = getPolicyStoreDelegate().findById(id, resourceServerId);
|
||||||
|
if (model == null) return null;
|
||||||
|
if (invalidations.contains(id)) return model;
|
||||||
|
cached = new CachedPolicy(loaded, model);
|
||||||
|
cache.addRevisioned(cached, startupRevision);
|
||||||
|
wasCached =true;
|
||||||
|
} else if (invalidations.contains(id)) {
|
||||||
|
return getPolicyStoreDelegate().findById(id, resourceServerId);
|
||||||
|
} else if (managedPolicies.containsKey(id)) {
|
||||||
|
return managedPolicies.get(id);
|
||||||
|
}
|
||||||
|
PolicyAdapter adapter = new PolicyAdapter(cached, StoreFactoryCacheSession.this);
|
||||||
|
managedPolicies.put(id, adapter);
|
||||||
|
return adapter;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Policy findByName(String name, String resourceServerId) {
|
||||||
|
if (name == null) return null;
|
||||||
|
String cacheKey = getPolicyByNameCacheKey(name, resourceServerId);
|
||||||
|
PolicyListQuery query = cache.get(cacheKey, PolicyListQuery.class);
|
||||||
|
if (query != null) {
|
||||||
|
logger.tracev("policy by name cache hit: {0}", name);
|
||||||
|
}
|
||||||
|
if (query == null) {
|
||||||
|
Long loaded = cache.getCurrentRevision(cacheKey);
|
||||||
|
Policy model = getPolicyStoreDelegate().findByName(name, resourceServerId);
|
||||||
|
if (model == null) return null;
|
||||||
|
if (invalidations.contains(model.getId())) return model;
|
||||||
|
query = new PolicyListQuery(loaded, cacheKey, model.getId(), resourceServerId);
|
||||||
|
cache.addRevisioned(query, startupRevision);
|
||||||
|
return model;
|
||||||
|
} else if (invalidations.contains(cacheKey)) {
|
||||||
|
return getPolicyStoreDelegate().findByName(name, resourceServerId);
|
||||||
|
} else {
|
||||||
|
String id = query.getPolicies().iterator().next();
|
||||||
|
if (invalidations.contains(id)) {
|
||||||
|
return getPolicyStoreDelegate().findByName(name, resourceServerId);
|
||||||
|
}
|
||||||
|
return findById(id, query.getResourceServerId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Policy> findByResourceServer(String resourceServerId) {
|
||||||
|
return getPolicyStoreDelegate().findByResourceServer(resourceServerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Policy> findByResourceServer(Map<String, String[]> attributes, String resourceServerId, int firstResult, int maxResult) {
|
||||||
|
return getPolicyStoreDelegate().findByResourceServer(attributes, resourceServerId, firstResult, maxResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Policy> findByResource(String resourceId, String resourceServerId) {
|
||||||
|
return getPolicyStoreDelegate().findByResource(resourceId, resourceServerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Policy> findByResourceType(String resourceType, String resourceServerId) {
|
||||||
|
return getPolicyStoreDelegate().findByResourceType(resourceType, resourceServerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Policy> findByScopeIds(List<String> scopeIds, String resourceServerId) {
|
||||||
|
return getPolicyStoreDelegate().findByScopeIds(scopeIds, resourceServerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Policy> findByType(String type, String resourceServerId) {
|
||||||
|
return getPolicyStoreDelegate().findByType(type, resourceServerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Policy> findDependentPolicies(String id, String resourceServerId) {
|
||||||
|
return getPolicyStoreDelegate().findDependentPolicies(id, resourceServerId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -16,12 +16,13 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.keycloak.models.authorization.infinispan.entities;
|
package org.keycloak.models.cache.infinispan.authorization.entities;
|
||||||
|
|
||||||
import org.keycloak.authorization.model.Policy;
|
import org.keycloak.authorization.model.Policy;
|
||||||
import org.keycloak.authorization.model.Resource;
|
import org.keycloak.authorization.model.Resource;
|
||||||
import org.keycloak.authorization.model.ResourceServer;
|
import org.keycloak.authorization.model.ResourceServer;
|
||||||
import org.keycloak.authorization.model.Scope;
|
import org.keycloak.authorization.model.Scope;
|
||||||
|
import org.keycloak.models.cache.infinispan.entities.AbstractRevisioned;
|
||||||
import org.keycloak.representations.idm.authorization.DecisionStrategy;
|
import org.keycloak.representations.idm.authorization.DecisionStrategy;
|
||||||
import org.keycloak.representations.idm.authorization.Logic;
|
import org.keycloak.representations.idm.authorization.Logic;
|
||||||
|
|
||||||
|
@ -34,11 +35,8 @@ import java.util.stream.Collectors;
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||||
*/
|
*/
|
||||||
public class CachedPolicy implements Policy, Serializable {
|
public class CachedPolicy extends AbstractRevisioned implements InResourceServer {
|
||||||
|
|
||||||
private static final long serialVersionUID = -144247681046298128L;
|
|
||||||
|
|
||||||
private String id;
|
|
||||||
private String type;
|
private String type;
|
||||||
private DecisionStrategy decisionStrategy;
|
private DecisionStrategy decisionStrategy;
|
||||||
private Logic logic;
|
private Logic logic;
|
||||||
|
@ -50,8 +48,8 @@ public class CachedPolicy implements Policy, Serializable {
|
||||||
private Set<String> resourcesIds;
|
private Set<String> resourcesIds;
|
||||||
private Set<String> scopesIds;
|
private Set<String> scopesIds;
|
||||||
|
|
||||||
public CachedPolicy(Policy policy) {
|
public CachedPolicy(Long revision, Policy policy) {
|
||||||
this.id = policy.getId();
|
super(revision, policy.getId());
|
||||||
this.type = policy.getType();
|
this.type = policy.getType();
|
||||||
this.decisionStrategy = policy.getDecisionStrategy();
|
this.decisionStrategy = policy.getDecisionStrategy();
|
||||||
this.logic = policy.getLogic();
|
this.logic = policy.getLogic();
|
||||||
|
@ -64,120 +62,30 @@ public class CachedPolicy implements Policy, Serializable {
|
||||||
this.scopesIds = policy.getScopes().stream().map(Scope::getId).collect(Collectors.toSet());
|
this.scopesIds = policy.getScopes().stream().map(Scope::getId).collect(Collectors.toSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
public CachedPolicy(String id) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getId() {
|
|
||||||
return this.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getType() {
|
public String getType() {
|
||||||
return this.type;
|
return this.type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public DecisionStrategy getDecisionStrategy() {
|
public DecisionStrategy getDecisionStrategy() {
|
||||||
return this.decisionStrategy;
|
return this.decisionStrategy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setDecisionStrategy(DecisionStrategy decisionStrategy) {
|
|
||||||
this.decisionStrategy = decisionStrategy;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Logic getLogic() {
|
public Logic getLogic() {
|
||||||
return this.logic;
|
return this.logic;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setLogic(Logic logic) {
|
|
||||||
this.logic = logic;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, String> getConfig() {
|
public Map<String, String> getConfig() {
|
||||||
return this.config;
|
return this.config;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setConfig(Map<String, String> config) {
|
|
||||||
this.config = config;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return this.name;
|
return this.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setName(String name) {
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getDescription() {
|
public String getDescription() {
|
||||||
return this.description;
|
return this.description;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setDescription(String description) {
|
|
||||||
this.description = description;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ResourceServer getResourceServer() {
|
|
||||||
throw new RuntimeException("Not implemented");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addScope(Scope scope) {
|
|
||||||
this.scopesIds.add(scope.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void removeScope(Scope scope) {
|
|
||||||
this.scopesIds.remove(scope.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addAssociatedPolicy(Policy associatedPolicy) {
|
|
||||||
this.associatedPoliciesIds.add(associatedPolicy.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void removeAssociatedPolicy(Policy associatedPolicy) {
|
|
||||||
this.associatedPoliciesIds.remove(associatedPolicy.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addResource(Resource resource) {
|
|
||||||
this.resourcesIds.add(resource.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void removeResource(Resource resource) {
|
|
||||||
this.resourcesIds.remove(resource.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<Policy> getAssociatedPolicies() {
|
|
||||||
throw new RuntimeException("Not implemented");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<Resource> getResources() {
|
|
||||||
throw new RuntimeException("Not implemented");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<Scope> getScopes() {
|
|
||||||
throw new RuntimeException("Not implemented");
|
|
||||||
}
|
|
||||||
|
|
||||||
public Set<String> getAssociatedPoliciesIds() {
|
public Set<String> getAssociatedPoliciesIds() {
|
||||||
return this.associatedPoliciesIds;
|
return this.associatedPoliciesIds;
|
||||||
}
|
}
|
||||||
|
@ -194,24 +102,4 @@ public class CachedPolicy implements Policy, Serializable {
|
||||||
return this.resourceServerId;
|
return this.resourceServerId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (o == this) return true;
|
|
||||||
|
|
||||||
if (this.id == null) return false;
|
|
||||||
|
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
|
||||||
|
|
||||||
Policy that = (Policy) o;
|
|
||||||
|
|
||||||
if (!getId().equals(that.getId())) return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return id!=null ? id.hashCode() : super.hashCode();
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -16,11 +16,12 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.keycloak.models.authorization.infinispan.entities;
|
package org.keycloak.models.cache.infinispan.authorization.entities;
|
||||||
|
|
||||||
import org.keycloak.authorization.model.Resource;
|
import org.keycloak.authorization.model.Resource;
|
||||||
import org.keycloak.authorization.model.ResourceServer;
|
import org.keycloak.authorization.model.ResourceServer;
|
||||||
import org.keycloak.authorization.model.Scope;
|
import org.keycloak.authorization.model.Scope;
|
||||||
|
import org.keycloak.models.cache.infinispan.entities.AbstractRevisioned;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -30,11 +31,8 @@ import java.util.stream.Collectors;
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||||
*/
|
*/
|
||||||
public class CachedResource implements Resource, Serializable {
|
public class CachedResource extends AbstractRevisioned implements InResourceServer {
|
||||||
|
|
||||||
private static final long serialVersionUID = -6886179034626995165L;
|
|
||||||
|
|
||||||
private final String id;
|
|
||||||
private String resourceServerId;
|
private String resourceServerId;
|
||||||
private String iconUri;
|
private String iconUri;
|
||||||
private String owner;
|
private String owner;
|
||||||
|
@ -43,8 +41,8 @@ public class CachedResource implements Resource, Serializable {
|
||||||
private String uri;
|
private String uri;
|
||||||
private Set<String> scopesIds;
|
private Set<String> scopesIds;
|
||||||
|
|
||||||
public CachedResource(Resource resource) {
|
public CachedResource(Long revision, Resource resource) {
|
||||||
this.id = resource.getId();
|
super(revision, resource.getId());
|
||||||
this.name = resource.getName();
|
this.name = resource.getName();
|
||||||
this.uri = resource.getUri();
|
this.uri = resource.getUri();
|
||||||
this.type = resource.getType();
|
this.type = resource.getType();
|
||||||
|
@ -54,76 +52,27 @@ public class CachedResource implements Resource, Serializable {
|
||||||
this.scopesIds = resource.getScopes().stream().map(Scope::getId).collect(Collectors.toSet());
|
this.scopesIds = resource.getScopes().stream().map(Scope::getId).collect(Collectors.toSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
public CachedResource(String id) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getId() {
|
|
||||||
return this.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return this.name;
|
return this.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setName(String name) {
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getUri() {
|
public String getUri() {
|
||||||
return this.uri;
|
return this.uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setUri(String uri) {
|
|
||||||
this.uri = uri;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getType() {
|
public String getType() {
|
||||||
return this.type;
|
return this.type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setType(String type) {
|
|
||||||
this.type = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<Scope> getScopes() {
|
|
||||||
throw new RuntimeException("Not implemented");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getIconUri() {
|
public String getIconUri() {
|
||||||
return this.iconUri;
|
return this.iconUri;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setIconUri(String iconUri) {
|
|
||||||
this.iconUri = iconUri;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ResourceServer getResourceServer() {
|
|
||||||
throw new RuntimeException("Not implemented");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getOwner() {
|
public String getOwner() {
|
||||||
return this.owner;
|
return this.owner;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateScopes(Set<Scope> scopes) {
|
|
||||||
this.scopesIds.clear();
|
|
||||||
this.scopesIds.addAll(scopes.stream().map(Scope::getId).collect(Collectors.toSet()));
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getResourceServerId() {
|
public String getResourceServerId() {
|
||||||
return this.resourceServerId;
|
return this.resourceServerId;
|
||||||
}
|
}
|
|
@ -16,9 +16,10 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.keycloak.models.authorization.infinispan.entities;
|
package org.keycloak.models.cache.infinispan.authorization.entities;
|
||||||
|
|
||||||
import org.keycloak.authorization.model.ResourceServer;
|
import org.keycloak.authorization.model.ResourceServer;
|
||||||
|
import org.keycloak.models.cache.infinispan.entities.AbstractRevisioned;
|
||||||
import org.keycloak.representations.idm.authorization.PolicyEnforcementMode;
|
import org.keycloak.representations.idm.authorization.PolicyEnforcementMode;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
@ -26,53 +27,30 @@ import java.io.Serializable;
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||||
*/
|
*/
|
||||||
public class CachedResourceServer implements ResourceServer, Serializable {
|
public class CachedResourceServer extends AbstractRevisioned {
|
||||||
|
|
||||||
private static final long serialVersionUID = 5054253390723121289L;
|
|
||||||
|
|
||||||
private final String id;
|
|
||||||
private String clientId;
|
private String clientId;
|
||||||
private boolean allowRemoteResourceManagement;
|
private boolean allowRemoteResourceManagement;
|
||||||
private PolicyEnforcementMode policyEnforcementMode;
|
private PolicyEnforcementMode policyEnforcementMode;
|
||||||
|
|
||||||
public CachedResourceServer(ResourceServer resourceServer) {
|
public CachedResourceServer(Long revision, ResourceServer resourceServer) {
|
||||||
this.id = resourceServer.getId();
|
super(revision, resourceServer.getId());
|
||||||
this.clientId = resourceServer.getClientId();
|
this.clientId = resourceServer.getClientId();
|
||||||
this.allowRemoteResourceManagement = resourceServer.isAllowRemoteResourceManagement();
|
this.allowRemoteResourceManagement = resourceServer.isAllowRemoteResourceManagement();
|
||||||
this.policyEnforcementMode = resourceServer.getPolicyEnforcementMode();
|
this.policyEnforcementMode = resourceServer.getPolicyEnforcementMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
public CachedResourceServer(String id) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getId() {
|
|
||||||
return this.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getClientId() {
|
public String getClientId() {
|
||||||
return this.clientId;
|
return this.clientId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isAllowRemoteResourceManagement() {
|
public boolean isAllowRemoteResourceManagement() {
|
||||||
return this.allowRemoteResourceManagement;
|
return this.allowRemoteResourceManagement;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setAllowRemoteResourceManagement(boolean allowRemoteResourceManagement) {
|
|
||||||
this.allowRemoteResourceManagement = allowRemoteResourceManagement;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PolicyEnforcementMode getPolicyEnforcementMode() {
|
public PolicyEnforcementMode getPolicyEnforcementMode() {
|
||||||
return this.policyEnforcementMode;
|
return this.policyEnforcementMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setPolicyEnforcementMode(PolicyEnforcementMode enforcementMode) {
|
|
||||||
this.policyEnforcementMode = enforcementMode;
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -16,10 +16,11 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.keycloak.models.authorization.infinispan.entities;
|
package org.keycloak.models.cache.infinispan.authorization.entities;
|
||||||
|
|
||||||
import org.keycloak.authorization.model.ResourceServer;
|
import org.keycloak.authorization.model.ResourceServer;
|
||||||
import org.keycloak.authorization.model.Scope;
|
import org.keycloak.authorization.model.Scope;
|
||||||
|
import org.keycloak.models.cache.infinispan.entities.AbstractRevisioned;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
@ -27,70 +28,30 @@ import java.util.Objects;
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||||
*/
|
*/
|
||||||
public class CachedScope implements Scope, Serializable {
|
public class CachedScope extends AbstractRevisioned implements InResourceServer {
|
||||||
|
|
||||||
private static final long serialVersionUID = -3919706923417065454L;
|
|
||||||
|
|
||||||
private final String id;
|
|
||||||
private String resourceServerId;
|
private String resourceServerId;
|
||||||
private String name;
|
private String name;
|
||||||
private String iconUri;
|
private String iconUri;
|
||||||
|
|
||||||
public CachedScope(Scope scope) {
|
public CachedScope(Long revision, Scope scope) {
|
||||||
this.id = scope.getId();
|
super(revision, scope.getId());
|
||||||
this.name = scope.getName();
|
this.name = scope.getName();
|
||||||
this.iconUri = scope.getIconUri();
|
this.iconUri = scope.getIconUri();
|
||||||
this.resourceServerId = scope.getResourceServer().getId();
|
this.resourceServerId = scope.getResourceServer().getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
public CachedScope(String id) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getId() {
|
|
||||||
return this.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return this.name;
|
return this.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setName(String name) {
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getIconUri() {
|
public String getIconUri() {
|
||||||
return this.iconUri;
|
return this.iconUri;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setIconUri(String iconUri) {
|
|
||||||
this.iconUri = iconUri;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ResourceServer getResourceServer() {
|
|
||||||
throw new RuntimeException("Not implemented");
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getResourceServerId() {
|
public String getResourceServerId() {
|
||||||
return this.resourceServerId;
|
return this.resourceServerId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) return true;
|
|
||||||
if (o == null || !Scope.class.isInstance(o)) return false;
|
|
||||||
Scope that = (Scope) o;
|
|
||||||
return Objects.equals(id, that.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hash(id);
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||||
|
* and other contributors as indicated by the @author tags.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.keycloak.models.cache.infinispan.authorization.entities;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public interface InResourceServer {
|
||||||
|
String getResourceServerId();
|
||||||
|
}
|
36
model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/authorization/entities/PolicyListQuery.java
vendored
Executable file
36
model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/authorization/entities/PolicyListQuery.java
vendored
Executable file
|
@ -0,0 +1,36 @@
|
||||||
|
package org.keycloak.models.cache.infinispan.authorization.entities;
|
||||||
|
|
||||||
|
import org.keycloak.models.cache.infinispan.entities.AbstractRevisioned;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class PolicyListQuery extends AbstractRevisioned implements InResourceServer {
|
||||||
|
private final Set<String> policies;
|
||||||
|
private final String serverId;
|
||||||
|
|
||||||
|
public PolicyListQuery(Long revision, String id, String policyId, String serverId) {
|
||||||
|
super(revision, id);
|
||||||
|
this.serverId = serverId;
|
||||||
|
policies = new HashSet<>();
|
||||||
|
policies.add(policyId);
|
||||||
|
}
|
||||||
|
public PolicyListQuery(Long revision, String id, Set<String> policies, String serverId) {
|
||||||
|
super(revision, id);
|
||||||
|
this.serverId = serverId;
|
||||||
|
this.policies = policies;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getResourceServerId() {
|
||||||
|
return serverId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<String> getPolicies() {
|
||||||
|
return policies;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
package org.keycloak.models.cache.infinispan.authorization.entities;
|
||||||
|
|
||||||
|
import org.keycloak.models.cache.infinispan.entities.AbstractRevisioned;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class ResourceListQuery extends AbstractRevisioned implements InResourceServer {
|
||||||
|
private final Set<String> resources;
|
||||||
|
private final String serverId;
|
||||||
|
|
||||||
|
public ResourceListQuery(Long revision, String id, String resourceId, String serverId) {
|
||||||
|
super(revision, id);
|
||||||
|
this.serverId = serverId;
|
||||||
|
resources = new HashSet<>();
|
||||||
|
resources.add(resourceId);
|
||||||
|
}
|
||||||
|
public ResourceListQuery(Long revision, String id, Set<String> resources, String serverId) {
|
||||||
|
super(revision, id);
|
||||||
|
this.serverId = serverId;
|
||||||
|
this.resources = resources;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getResourceServerId() {
|
||||||
|
return serverId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<String> getResources() {
|
||||||
|
return resources;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package org.keycloak.models.cache.infinispan.authorization.entities;
|
||||||
|
|
||||||
|
import org.keycloak.models.cache.infinispan.entities.AbstractRevisioned;
|
||||||
|
import org.keycloak.models.cache.infinispan.entities.RealmQuery;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class ResourceServerListQuery extends AbstractRevisioned {
|
||||||
|
private final Set<String> servers;
|
||||||
|
|
||||||
|
public ResourceServerListQuery(Long revision, String id, String serverId) {
|
||||||
|
super(revision, id);
|
||||||
|
servers = new HashSet<>();
|
||||||
|
servers.add(serverId);
|
||||||
|
}
|
||||||
|
public ResourceServerListQuery(Long revision, String id, Set<String> servers) {
|
||||||
|
super(revision, id);
|
||||||
|
this.servers = servers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<String> getResourceServers() {
|
||||||
|
return servers;
|
||||||
|
}
|
||||||
|
}
|
36
model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/authorization/entities/ScopeListQuery.java
vendored
Executable file
36
model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/authorization/entities/ScopeListQuery.java
vendored
Executable file
|
@ -0,0 +1,36 @@
|
||||||
|
package org.keycloak.models.cache.infinispan.authorization.entities;
|
||||||
|
|
||||||
|
import org.keycloak.models.cache.infinispan.entities.AbstractRevisioned;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class ScopeListQuery extends AbstractRevisioned implements InResourceServer {
|
||||||
|
private final Set<String> scopes;
|
||||||
|
private final String serverId;
|
||||||
|
|
||||||
|
public ScopeListQuery(Long revision, String id, String scopeId, String serverId) {
|
||||||
|
super(revision, id);
|
||||||
|
this.serverId = serverId;
|
||||||
|
scopes = new HashSet<>();
|
||||||
|
scopes.add(scopeId);
|
||||||
|
}
|
||||||
|
public ScopeListQuery(Long revision, String id, Set<String> scopes, String serverId) {
|
||||||
|
super(revision, id);
|
||||||
|
this.serverId = serverId;
|
||||||
|
this.scopes = scopes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getResourceServerId() {
|
||||||
|
return serverId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<String> getScopes() {
|
||||||
|
return scopes;
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,23 +14,16 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.keycloak.models.authorization.infinispan.events;
|
package org.keycloak.models.cache.infinispan.authorization.events;
|
||||||
|
|
||||||
import java.util.Collections;
|
import org.keycloak.models.cache.infinispan.authorization.StoreFactoryCacheManager;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
*/
|
*/
|
||||||
public class ResourceServerRemovedEvent extends AuthorizationInvalidationEvent {
|
public interface AuthorizationCacheInvalidationEvent {
|
||||||
|
void addInvalidations(StoreFactoryCacheManager realmCache, Set<String> invalidations);
|
||||||
private final String clientId;
|
|
||||||
|
|
||||||
public ResourceServerRemovedEvent(String id, String clientId) {
|
|
||||||
super(id, Collections.emptySet());
|
|
||||||
this.clientId = clientId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getClientId() {
|
|
||||||
return clientId;
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||||
|
* and other contributors as indicated by the @author tags.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.keycloak.models.cache.infinispan.authorization.events;
|
||||||
|
|
||||||
|
import org.keycloak.models.cache.infinispan.authorization.StoreFactoryCacheManager;
|
||||||
|
import org.keycloak.models.cache.infinispan.events.InvalidationEvent;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
|
*/
|
||||||
|
public class PolicyRemovedEvent extends InvalidationEvent implements AuthorizationCacheInvalidationEvent {
|
||||||
|
|
||||||
|
private String id;
|
||||||
|
private String name;
|
||||||
|
private String serverId;
|
||||||
|
|
||||||
|
public static PolicyRemovedEvent create(String id, String name, String serverId) {
|
||||||
|
PolicyRemovedEvent event = new PolicyRemovedEvent();
|
||||||
|
event.id = id;
|
||||||
|
event.name = name;
|
||||||
|
event.serverId = serverId;
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format("PolicyRemovedEvent [ id=%s, name=%s]", id, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addInvalidations(StoreFactoryCacheManager cache, Set<String> invalidations) {
|
||||||
|
cache.policyRemoval(id, name, serverId, invalidations);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||||
|
* and other contributors as indicated by the @author tags.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.keycloak.models.cache.infinispan.authorization.events;
|
||||||
|
|
||||||
|
import org.keycloak.models.cache.infinispan.authorization.StoreFactoryCacheManager;
|
||||||
|
import org.keycloak.models.cache.infinispan.events.InvalidationEvent;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
|
*/
|
||||||
|
public class PolicyUpdatedEvent extends InvalidationEvent implements AuthorizationCacheInvalidationEvent {
|
||||||
|
|
||||||
|
private String id;
|
||||||
|
private String name;
|
||||||
|
private String serverId;
|
||||||
|
|
||||||
|
public static PolicyUpdatedEvent create(String id, String name, String serverId) {
|
||||||
|
PolicyUpdatedEvent event = new PolicyUpdatedEvent();
|
||||||
|
event.id = id;
|
||||||
|
event.name = name;
|
||||||
|
event.serverId = serverId;
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format("PolicyUpdatedEvent [ id=%s, name=%s ]", id, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addInvalidations(StoreFactoryCacheManager cache, Set<String> invalidations) {
|
||||||
|
cache.policyUpdated(id, name, serverId, invalidations);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||||
|
* and other contributors as indicated by the @author tags.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.keycloak.models.cache.infinispan.authorization.events;
|
||||||
|
|
||||||
|
import org.keycloak.models.cache.infinispan.authorization.StoreFactoryCacheManager;
|
||||||
|
import org.keycloak.models.cache.infinispan.events.InvalidationEvent;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
|
*/
|
||||||
|
public class ResourceRemovedEvent extends InvalidationEvent implements AuthorizationCacheInvalidationEvent {
|
||||||
|
|
||||||
|
private String id;
|
||||||
|
private String name;
|
||||||
|
private String serverId;
|
||||||
|
|
||||||
|
public static ResourceRemovedEvent create(String id, String name, String serverId) {
|
||||||
|
ResourceRemovedEvent event = new ResourceRemovedEvent();
|
||||||
|
event.id = id;
|
||||||
|
event.name = name;
|
||||||
|
event.serverId = serverId;
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format("ResourceRemovedEvent [ id=%s, name=%s ]", id, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addInvalidations(StoreFactoryCacheManager cache, Set<String> invalidations) {
|
||||||
|
cache.resourceRemoval(id, name, serverId, invalidations);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||||
|
* and other contributors as indicated by the @author tags.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.keycloak.models.cache.infinispan.authorization.events;
|
||||||
|
|
||||||
|
import org.keycloak.models.cache.infinispan.authorization.StoreFactoryCacheManager;
|
||||||
|
import org.keycloak.models.cache.infinispan.events.InvalidationEvent;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
|
*/
|
||||||
|
public class ResourceServerRemovedEvent extends InvalidationEvent implements AuthorizationCacheInvalidationEvent {
|
||||||
|
|
||||||
|
private String id;
|
||||||
|
private String clientId;
|
||||||
|
|
||||||
|
public static ResourceServerRemovedEvent create(String id, String clientId) {
|
||||||
|
ResourceServerRemovedEvent event = new ResourceServerRemovedEvent();
|
||||||
|
event.id = id;
|
||||||
|
event.clientId = clientId;
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format("ResourceServerRemovedEvent [ id=%s, clientId=%s ]", id, clientId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addInvalidations(StoreFactoryCacheManager cache, Set<String> invalidations) {
|
||||||
|
cache.resourceServerRemoval(id, clientId, invalidations);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||||
|
* and other contributors as indicated by the @author tags.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.keycloak.models.cache.infinispan.authorization.events;
|
||||||
|
|
||||||
|
import org.keycloak.models.cache.infinispan.authorization.StoreFactoryCacheManager;
|
||||||
|
import org.keycloak.models.cache.infinispan.events.InvalidationEvent;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
|
*/
|
||||||
|
public class ResourceServerUpdatedEvent extends InvalidationEvent implements AuthorizationCacheInvalidationEvent {
|
||||||
|
|
||||||
|
private String id;
|
||||||
|
private String clientId;
|
||||||
|
|
||||||
|
public static ResourceServerUpdatedEvent create(String id, String clientId) {
|
||||||
|
ResourceServerUpdatedEvent event = new ResourceServerUpdatedEvent();
|
||||||
|
event.id = id;
|
||||||
|
event.clientId = clientId;
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format("ResourceServerRemovedEvent [ id=%s, clientId=%s ]", id, clientId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addInvalidations(StoreFactoryCacheManager cache, Set<String> invalidations) {
|
||||||
|
cache.resourceServerUpdated(id, clientId, invalidations);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||||
|
* and other contributors as indicated by the @author tags.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.keycloak.models.cache.infinispan.authorization.events;
|
||||||
|
|
||||||
|
import org.keycloak.models.cache.infinispan.authorization.StoreFactoryCacheManager;
|
||||||
|
import org.keycloak.models.cache.infinispan.events.InvalidationEvent;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
|
*/
|
||||||
|
public class ResourceUpdatedEvent extends InvalidationEvent implements AuthorizationCacheInvalidationEvent {
|
||||||
|
|
||||||
|
private String id;
|
||||||
|
private String name;
|
||||||
|
private String serverId;
|
||||||
|
|
||||||
|
public static ResourceUpdatedEvent create(String id, String name, String serverId) {
|
||||||
|
ResourceUpdatedEvent event = new ResourceUpdatedEvent();
|
||||||
|
event.id = id;
|
||||||
|
event.name = name;
|
||||||
|
event.serverId = serverId;
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format("ResourceUpdatedEvent [ id=%s, name=%s ]", id, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addInvalidations(StoreFactoryCacheManager cache, Set<String> invalidations) {
|
||||||
|
cache.resourceUpdated(id, name, serverId, invalidations);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||||
|
* and other contributors as indicated by the @author tags.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.keycloak.models.cache.infinispan.authorization.events;
|
||||||
|
|
||||||
|
import org.keycloak.models.cache.infinispan.authorization.StoreFactoryCacheManager;
|
||||||
|
import org.keycloak.models.cache.infinispan.events.InvalidationEvent;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
|
*/
|
||||||
|
public class ScopeRemovedEvent extends InvalidationEvent implements AuthorizationCacheInvalidationEvent {
|
||||||
|
|
||||||
|
private String id;
|
||||||
|
private String name;
|
||||||
|
private String serverId;
|
||||||
|
|
||||||
|
public static ScopeRemovedEvent create(String id, String name, String serverId) {
|
||||||
|
ScopeRemovedEvent event = new ScopeRemovedEvent();
|
||||||
|
event.id = id;
|
||||||
|
event.name = name;
|
||||||
|
event.serverId = serverId;
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format("ScopeRemovedEvent [ id=%s, name=%s]", id, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addInvalidations(StoreFactoryCacheManager cache, Set<String> invalidations) {
|
||||||
|
cache.scopeRemoval(id, name, serverId, invalidations);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||||
|
* and other contributors as indicated by the @author tags.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.keycloak.models.cache.infinispan.authorization.events;
|
||||||
|
|
||||||
|
import org.keycloak.models.cache.infinispan.authorization.StoreFactoryCacheManager;
|
||||||
|
import org.keycloak.models.cache.infinispan.events.InvalidationEvent;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
|
*/
|
||||||
|
public class ScopeUpdatedEvent extends InvalidationEvent implements AuthorizationCacheInvalidationEvent {
|
||||||
|
|
||||||
|
private String id;
|
||||||
|
private String name;
|
||||||
|
private String serverId;
|
||||||
|
|
||||||
|
public static ScopeUpdatedEvent create(String id, String name, String serverId) {
|
||||||
|
ScopeUpdatedEvent event = new ScopeUpdatedEvent();
|
||||||
|
event.id = id;
|
||||||
|
event.name = name;
|
||||||
|
event.serverId = serverId;
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format("ScopeUpdatedEvent [ id=%s, name=%s ]", id, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addInvalidations(StoreFactoryCacheManager cache, Set<String> invalidations) {
|
||||||
|
cache.scopeUpdated(id, name, serverId, invalidations);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
package org.keycloak.models.cache.infinispan.authorization.stream;
|
||||||
|
|
||||||
|
import org.keycloak.models.cache.infinispan.authorization.entities.InResourceServer;
|
||||||
|
import org.keycloak.models.cache.infinispan.entities.InRealm;
|
||||||
|
import org.keycloak.models.cache.infinispan.entities.Revisioned;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class InResourceServerPredicate implements Predicate<Map.Entry<String, Revisioned>>, Serializable {
|
||||||
|
private String serverId;
|
||||||
|
|
||||||
|
public static InResourceServerPredicate create() {
|
||||||
|
return new InResourceServerPredicate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public InResourceServerPredicate resourceServer(String id) {
|
||||||
|
serverId = id;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean test(Map.Entry<String, Revisioned> entry) {
|
||||||
|
Object value = entry.getValue();
|
||||||
|
if (value == null) return false;
|
||||||
|
if (!(value instanceof InResourceServer)) return false;
|
||||||
|
|
||||||
|
return serverId.equals(((InResourceServer)value).getResourceServerId());
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,4 +16,4 @@
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
#
|
#
|
||||||
|
|
||||||
org.keycloak.models.authorization.infinispan.InfinispanStoreProviderFactory
|
org.keycloak.models.cache.infinispan.authorization.InfinispanCacheStoreFactoryProviderFactory
|
|
@ -35,6 +35,8 @@ import javax.persistence.JoinColumn;
|
||||||
import javax.persistence.JoinTable;
|
import javax.persistence.JoinTable;
|
||||||
import javax.persistence.ManyToOne;
|
import javax.persistence.ManyToOne;
|
||||||
import javax.persistence.MapKeyColumn;
|
import javax.persistence.MapKeyColumn;
|
||||||
|
import javax.persistence.NamedQueries;
|
||||||
|
import javax.persistence.NamedQuery;
|
||||||
import javax.persistence.OneToMany;
|
import javax.persistence.OneToMany;
|
||||||
import javax.persistence.Table;
|
import javax.persistence.Table;
|
||||||
import javax.persistence.UniqueConstraint;
|
import javax.persistence.UniqueConstraint;
|
||||||
|
@ -52,11 +54,25 @@ import org.keycloak.representations.idm.authorization.Logic;
|
||||||
@Table(name = "RESOURCE_SERVER_POLICY", uniqueConstraints = {
|
@Table(name = "RESOURCE_SERVER_POLICY", uniqueConstraints = {
|
||||||
@UniqueConstraint(columnNames = {"NAME", "RESOURCE_SERVER_ID"})
|
@UniqueConstraint(columnNames = {"NAME", "RESOURCE_SERVER_ID"})
|
||||||
})
|
})
|
||||||
public class PolicyEntity implements Policy {
|
@NamedQueries(
|
||||||
|
{
|
||||||
|
@NamedQuery(name="findPolicyIdByServerId", query="select p.id from PolicyEntity p where p.resourceServer.id = :serverId "),
|
||||||
|
@NamedQuery(name="findPolicyIdByName", query="select p.id from PolicyEntity p where p.resourceServer.id = :serverId and p.name = :name"),
|
||||||
|
@NamedQuery(name="findPolicyIdByResource", query="select p.id from PolicyEntity p inner join p.resources r where p.resourceServer.id = :serverId and (r.resourceServer.id = :serverId and r.id = :resourceId)"),
|
||||||
|
@NamedQuery(name="findPolicyIdByScope", query="select pe.id from PolicyEntity pe where pe.resourceServer.id = :serverId and pe.id IN (select p.id from ScopeEntity s inner join s.policies p where s.resourceServer.id = :serverId and (p.resourceServer.id = :serverId and p.type = 'scope' and s.id in (:scopeIds)))"),
|
||||||
|
@NamedQuery(name="findPolicyIdByType", query="select p.id from PolicyEntity p where p.resourceServer.id = :serverId and p.type = :type"),
|
||||||
|
@NamedQuery(name="findPolicyIdByResourceType", query="select p.id from PolicyEntity p inner join p.config c where p.resourceServer.id = :serverId and KEY(c) = 'defaultResourceType' and c like :type"),
|
||||||
|
@NamedQuery(name="findPolicyIdByDependentPolices", query="select p.id from PolicyEntity p inner join p.associatedPolicies ap where p.resourceServer.id = :serverId and (ap.resourceServer.id = :serverId and ap.id = :policyId)"),
|
||||||
|
@NamedQuery(name="deletePolicyByResourceServer", query="delete from PolicyEntity p where p.resourceServer.id = :serverId")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
public class PolicyEntity {
|
||||||
|
|
||||||
@Id
|
@Id
|
||||||
@Column(name="ID", length = 36)
|
@Column(name = "ID", length = 36)
|
||||||
@Access(AccessType.PROPERTY) // we do this because relationships often fetch id, but not entity. This avoids an extra SQL
|
@Access(AccessType.PROPERTY)
|
||||||
|
// we do this because relationships often fetch id, but not entity. This avoids an extra SQL
|
||||||
private String id;
|
private String id;
|
||||||
|
|
||||||
@Column(name = "NAME")
|
@Column(name = "NAME")
|
||||||
|
@ -75,9 +91,9 @@ public class PolicyEntity implements Policy {
|
||||||
private Logic logic = Logic.POSITIVE;
|
private Logic logic = Logic.POSITIVE;
|
||||||
|
|
||||||
@ElementCollection(fetch = FetchType.LAZY)
|
@ElementCollection(fetch = FetchType.LAZY)
|
||||||
@MapKeyColumn(name="NAME")
|
@MapKeyColumn(name = "NAME")
|
||||||
@Column(name="VALUE", columnDefinition = "TEXT")
|
@Column(name = "VALUE", columnDefinition = "TEXT")
|
||||||
@CollectionTable(name="POLICY_CONFIG", joinColumns={ @JoinColumn(name="POLICY_ID") })
|
@CollectionTable(name = "POLICY_CONFIG", joinColumns = {@JoinColumn(name = "POLICY_ID")})
|
||||||
private Map<String, String> config = new HashMap();
|
private Map<String, String> config = new HashMap();
|
||||||
|
|
||||||
@ManyToOne(optional = false, fetch = FetchType.LAZY)
|
@ManyToOne(optional = false, fetch = FetchType.LAZY)
|
||||||
|
@ -96,7 +112,6 @@ public class PolicyEntity implements Policy {
|
||||||
@JoinTable(name = "SCOPE_POLICY", joinColumns = @JoinColumn(name = "POLICY_ID"), inverseJoinColumns = @JoinColumn(name = "SCOPE_ID"))
|
@JoinTable(name = "SCOPE_POLICY", joinColumns = @JoinColumn(name = "POLICY_ID"), inverseJoinColumns = @JoinColumn(name = "SCOPE_ID"))
|
||||||
private Set<ScopeEntity> scopes = new HashSet<>();
|
private Set<ScopeEntity> scopes = new HashSet<>();
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return this.id;
|
return this.id;
|
||||||
}
|
}
|
||||||
|
@ -105,7 +120,6 @@ public class PolicyEntity implements Policy {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getType() {
|
public String getType() {
|
||||||
return this.type;
|
return this.type;
|
||||||
}
|
}
|
||||||
|
@ -114,57 +128,46 @@ public class PolicyEntity implements Policy {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public DecisionStrategy getDecisionStrategy() {
|
public DecisionStrategy getDecisionStrategy() {
|
||||||
return this.decisionStrategy;
|
return this.decisionStrategy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setDecisionStrategy(DecisionStrategy decisionStrategy) {
|
public void setDecisionStrategy(DecisionStrategy decisionStrategy) {
|
||||||
this.decisionStrategy = decisionStrategy;
|
this.decisionStrategy = decisionStrategy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Logic getLogic() {
|
public Logic getLogic() {
|
||||||
return this.logic;
|
return this.logic;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setLogic(Logic logic) {
|
public void setLogic(Logic logic) {
|
||||||
this.logic = logic;
|
this.logic = logic;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, String> getConfig() {
|
public Map<String, String> getConfig() {
|
||||||
return this.config;
|
return this.config;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setConfig(Map<String, String> config) {
|
public void setConfig(Map<String, String> config) {
|
||||||
this.config = config;
|
this.config = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return this.name;
|
return this.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setName(String name) {
|
public void setName(String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getDescription() {
|
public String getDescription() {
|
||||||
return this.description;
|
return this.description;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setDescription(String description) {
|
public void setDescription(String description) {
|
||||||
this.description = description;
|
this.description = description;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ResourceServerEntity getResourceServer() {
|
public ResourceServerEntity getResourceServer() {
|
||||||
return this.resourceServer;
|
return this.resourceServer;
|
||||||
}
|
}
|
||||||
|
@ -173,16 +176,6 @@ public class PolicyEntity implements Policy {
|
||||||
this.resourceServer = resourceServer;
|
this.resourceServer = resourceServer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public <P extends Policy> Set<P> getAssociatedPolicies() {
|
|
||||||
return (Set<P>) this.associatedPolicies;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAssociatedPolicies(Set<PolicyEntity> associatedPolicies) {
|
|
||||||
this.associatedPolicies = associatedPolicies;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<ResourceEntity> getResources() {
|
public Set<ResourceEntity> getResources() {
|
||||||
return this.resources;
|
return this.resources;
|
||||||
}
|
}
|
||||||
|
@ -191,7 +184,6 @@ public class PolicyEntity implements Policy {
|
||||||
this.resources = resources;
|
this.resources = resources;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<ScopeEntity> getScopes() {
|
public Set<ScopeEntity> getScopes() {
|
||||||
return this.scopes;
|
return this.scopes;
|
||||||
}
|
}
|
||||||
|
@ -200,54 +192,26 @@ public class PolicyEntity implements Policy {
|
||||||
this.scopes = scopes;
|
this.scopes = scopes;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public Set<PolicyEntity> getAssociatedPolicies() {
|
||||||
public void addScope(Scope scope) {
|
return associatedPolicies;
|
||||||
getScopes().add((ScopeEntity) scope);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void setAssociatedPolicies(Set<PolicyEntity> associatedPolicies) {
|
||||||
public void removeScope(Scope scope) {
|
this.associatedPolicies = associatedPolicies;
|
||||||
getScopes().remove(scope);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addAssociatedPolicy(Policy associatedPolicy) {
|
|
||||||
getAssociatedPolicies().add(associatedPolicy);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void removeAssociatedPolicy(Policy associatedPolicy) {
|
|
||||||
getAssociatedPolicies().remove(associatedPolicy);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addResource(Resource resource) {
|
|
||||||
getResources().add((ResourceEntity) resource);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void removeResource(Resource resource) {
|
|
||||||
getResources().remove(resource);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (o == this) return true;
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
|
||||||
if (this.id == null) return false;
|
PolicyEntity that = (PolicyEntity) o;
|
||||||
|
|
||||||
if (!Policy.class.isInstance(o)) return false;
|
|
||||||
|
|
||||||
Policy that = (Policy) o;
|
|
||||||
|
|
||||||
if (!getId().equals(that.getId())) return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
|
|
||||||
|
return getId().equals(that.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return id!=null ? id.hashCode() : super.hashCode();
|
return getId().hashCode();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,10 +31,13 @@ import javax.persistence.JoinColumn;
|
||||||
import javax.persistence.JoinTable;
|
import javax.persistence.JoinTable;
|
||||||
import javax.persistence.ManyToMany;
|
import javax.persistence.ManyToMany;
|
||||||
import javax.persistence.ManyToOne;
|
import javax.persistence.ManyToOne;
|
||||||
|
import javax.persistence.NamedQueries;
|
||||||
|
import javax.persistence.NamedQuery;
|
||||||
import javax.persistence.Table;
|
import javax.persistence.Table;
|
||||||
import javax.persistence.UniqueConstraint;
|
import javax.persistence.UniqueConstraint;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
@ -45,7 +48,18 @@ import java.util.Set;
|
||||||
@Table(name = "RESOURCE_SERVER_RESOURCE", uniqueConstraints = {
|
@Table(name = "RESOURCE_SERVER_RESOURCE", uniqueConstraints = {
|
||||||
@UniqueConstraint(columnNames = {"NAME", "RESOURCE_SERVER_ID", "OWNER"})
|
@UniqueConstraint(columnNames = {"NAME", "RESOURCE_SERVER_ID", "OWNER"})
|
||||||
})
|
})
|
||||||
public class ResourceEntity implements Resource {
|
@NamedQueries(
|
||||||
|
{
|
||||||
|
@NamedQuery(name="findResourceIdByOwner", query="select r.id from ResourceEntity r where r.resourceServer.id = :serverId and r.owner = :owner"),
|
||||||
|
@NamedQuery(name="findResourceIdByUri", query="select r.id from ResourceEntity r where r.resourceServer.id = :serverId and r.uri = :uri"),
|
||||||
|
@NamedQuery(name="findResourceIdByName", query="select r.id from ResourceEntity r where r.resourceServer.id = :serverId and r.name = :name"),
|
||||||
|
@NamedQuery(name="findResourceIdByType", query="select r.id from ResourceEntity r where r.resourceServer.id = :serverId and r.type = :type"),
|
||||||
|
@NamedQuery(name="findResourceIdByServerId", query="select r.id from ResourceEntity r where r.resourceServer.id = :serverId "),
|
||||||
|
@NamedQuery(name="findResourceIdByScope", query="select r.id from ResourceEntity r inner join r.scopes s where r.resourceServer.id = :serverId and (s.resourceServer.id = :serverId and s.id in (:scopeIds))"),
|
||||||
|
@NamedQuery(name="deleteResourceByResourceServer", query="delete from ResourceEntity r where r.resourceServer.id = :serverId")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
public class ResourceEntity {
|
||||||
|
|
||||||
@Id
|
@Id
|
||||||
@Column(name="ID", length = 36)
|
@Column(name="ID", length = 36)
|
||||||
|
@ -73,13 +87,12 @@ public class ResourceEntity implements Resource {
|
||||||
|
|
||||||
@ManyToMany(fetch = FetchType.LAZY, cascade = {})
|
@ManyToMany(fetch = FetchType.LAZY, cascade = {})
|
||||||
@JoinTable(name = "RESOURCE_SCOPE", joinColumns = @JoinColumn(name = "RESOURCE_ID"), inverseJoinColumns = @JoinColumn(name = "SCOPE_ID"))
|
@JoinTable(name = "RESOURCE_SCOPE", joinColumns = @JoinColumn(name = "RESOURCE_ID"), inverseJoinColumns = @JoinColumn(name = "SCOPE_ID"))
|
||||||
private List<ScopeEntity> scopes = new ArrayList<>();
|
private List<ScopeEntity> scopes = new LinkedList<>();
|
||||||
|
|
||||||
@ManyToMany(fetch = FetchType.LAZY, cascade = {})
|
@ManyToMany(fetch = FetchType.LAZY, cascade = {})
|
||||||
@JoinTable(name = "RESOURCE_POLICY", joinColumns = @JoinColumn(name = "RESOURCE_ID"), inverseJoinColumns = @JoinColumn(name = "POLICY_ID"))
|
@JoinTable(name = "RESOURCE_POLICY", joinColumns = @JoinColumn(name = "RESOURCE_ID"), inverseJoinColumns = @JoinColumn(name = "POLICY_ID"))
|
||||||
private List<PolicyEntity> policies = new ArrayList<>();
|
private List<PolicyEntity> policies = new LinkedList<>();
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
@ -88,52 +101,42 @@ public class ResourceEntity implements Resource {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setName(String name) {
|
public void setName(String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getUri() {
|
public String getUri() {
|
||||||
return uri;
|
return uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setUri(String uri) {
|
public void setUri(String uri) {
|
||||||
this.uri = uri;
|
this.uri = uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getType() {
|
public String getType() {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setType(String type) {
|
public void setType(String type) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<ScopeEntity> getScopes() {
|
public List<ScopeEntity> getScopes() {
|
||||||
return this.scopes;
|
return this.scopes;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getIconUri() {
|
public String getIconUri() {
|
||||||
return iconUri;
|
return iconUri;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setIconUri(String iconUri) {
|
public void setIconUri(String iconUri) {
|
||||||
this.iconUri = iconUri;
|
this.iconUri = iconUri;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ResourceServerEntity getResourceServer() {
|
public ResourceServerEntity getResourceServer() {
|
||||||
return resourceServer;
|
return resourceServer;
|
||||||
}
|
}
|
||||||
|
@ -154,37 +157,23 @@ public class ResourceEntity implements Resource {
|
||||||
return this.policies;
|
return this.policies;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateScopes(Set<Scope> toUpdate) {
|
|
||||||
for (Scope scope : toUpdate) {
|
|
||||||
boolean hasScope = false;
|
|
||||||
|
|
||||||
for (Scope existingScope : this.scopes) {
|
|
||||||
if (existingScope.equals(scope)) {
|
|
||||||
hasScope = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!hasScope) {
|
|
||||||
this.scopes.add((ScopeEntity) scope);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Scope scopeModel : new HashSet<Scope>(this.scopes)) {
|
|
||||||
boolean hasScope = false;
|
|
||||||
|
|
||||||
for (Scope scope : toUpdate) {
|
|
||||||
if (scopeModel.equals(scope)) {
|
|
||||||
hasScope = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!hasScope) {
|
|
||||||
this.scopes.remove(scopeModel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPolicies(List<PolicyEntity> policies) {
|
public void setPolicies(List<PolicyEntity> policies) {
|
||||||
this.policies = policies;
|
this.policies = policies;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
|
||||||
|
ResourceEntity that = (ResourceEntity) o;
|
||||||
|
|
||||||
|
return getId().equals(that.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return getId().hashCode();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,8 @@ import javax.persistence.AccessType;
|
||||||
import javax.persistence.Column;
|
import javax.persistence.Column;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
import javax.persistence.Id;
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.NamedQueries;
|
||||||
|
import javax.persistence.NamedQuery;
|
||||||
import javax.persistence.OneToMany;
|
import javax.persistence.OneToMany;
|
||||||
import javax.persistence.Table;
|
import javax.persistence.Table;
|
||||||
import javax.persistence.UniqueConstraint;
|
import javax.persistence.UniqueConstraint;
|
||||||
|
@ -36,7 +38,12 @@ import java.util.List;
|
||||||
*/
|
*/
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "RESOURCE_SERVER", uniqueConstraints = {@UniqueConstraint(columnNames = "CLIENT_ID")})
|
@Table(name = "RESOURCE_SERVER", uniqueConstraints = {@UniqueConstraint(columnNames = "CLIENT_ID")})
|
||||||
public class ResourceServerEntity implements ResourceServer {
|
@NamedQueries(
|
||||||
|
{
|
||||||
|
@NamedQuery(name="findResourceServerIdByClient", query="select r.id from ResourceServerEntity r where r.clientId = :clientId"),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
public class ResourceServerEntity {
|
||||||
|
|
||||||
@Id
|
@Id
|
||||||
@Column(name="ID", length = 36)
|
@Column(name="ID", length = 36)
|
||||||
|
@ -58,7 +65,6 @@ public class ResourceServerEntity implements ResourceServer {
|
||||||
@OneToMany (mappedBy = "resourceServer")
|
@OneToMany (mappedBy = "resourceServer")
|
||||||
private List<ScopeEntity> scopes;
|
private List<ScopeEntity> scopes;
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return this.id;
|
return this.id;
|
||||||
}
|
}
|
||||||
|
@ -67,7 +73,6 @@ public class ResourceServerEntity implements ResourceServer {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getClientId() {
|
public String getClientId() {
|
||||||
return this.clientId;
|
return this.clientId;
|
||||||
}
|
}
|
||||||
|
@ -76,22 +81,18 @@ public class ResourceServerEntity implements ResourceServer {
|
||||||
this.clientId = clientId;
|
this.clientId = clientId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isAllowRemoteResourceManagement() {
|
public boolean isAllowRemoteResourceManagement() {
|
||||||
return this.allowRemoteResourceManagement;
|
return this.allowRemoteResourceManagement;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setAllowRemoteResourceManagement(boolean allowRemoteResourceManagement) {
|
public void setAllowRemoteResourceManagement(boolean allowRemoteResourceManagement) {
|
||||||
this.allowRemoteResourceManagement = allowRemoteResourceManagement;
|
this.allowRemoteResourceManagement = allowRemoteResourceManagement;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public PolicyEnforcementMode getPolicyEnforcementMode() {
|
public PolicyEnforcementMode getPolicyEnforcementMode() {
|
||||||
return this.policyEnforcementMode;
|
return this.policyEnforcementMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setPolicyEnforcementMode(PolicyEnforcementMode policyEnforcementMode) {
|
public void setPolicyEnforcementMode(PolicyEnforcementMode policyEnforcementMode) {
|
||||||
this.policyEnforcementMode = policyEnforcementMode;
|
this.policyEnforcementMode = policyEnforcementMode;
|
||||||
}
|
}
|
||||||
|
@ -111,4 +112,19 @@ public class ResourceServerEntity implements ResourceServer {
|
||||||
public void setScopes(final List<ScopeEntity> scopes) {
|
public void setScopes(final List<ScopeEntity> scopes) {
|
||||||
this.scopes = scopes;
|
this.scopes = scopes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
|
||||||
|
ResourceServerEntity that = (ResourceServerEntity) o;
|
||||||
|
|
||||||
|
return getId().equals(that.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return getId().hashCode();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,8 @@ import javax.persistence.JoinColumn;
|
||||||
import javax.persistence.JoinTable;
|
import javax.persistence.JoinTable;
|
||||||
import javax.persistence.ManyToMany;
|
import javax.persistence.ManyToMany;
|
||||||
import javax.persistence.ManyToOne;
|
import javax.persistence.ManyToOne;
|
||||||
|
import javax.persistence.NamedQueries;
|
||||||
|
import javax.persistence.NamedQuery;
|
||||||
import javax.persistence.Table;
|
import javax.persistence.Table;
|
||||||
import javax.persistence.UniqueConstraint;
|
import javax.persistence.UniqueConstraint;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -44,7 +46,14 @@ import java.util.Objects;
|
||||||
@Table(name = "RESOURCE_SERVER_SCOPE", uniqueConstraints = {
|
@Table(name = "RESOURCE_SERVER_SCOPE", uniqueConstraints = {
|
||||||
@UniqueConstraint(columnNames = {"NAME", "RESOURCE_SERVER_ID"})
|
@UniqueConstraint(columnNames = {"NAME", "RESOURCE_SERVER_ID"})
|
||||||
})
|
})
|
||||||
public class ScopeEntity implements Scope {
|
@NamedQueries(
|
||||||
|
{
|
||||||
|
@NamedQuery(name="findScopeIdByName", query="select s.id from ScopeEntity s where s.resourceServer.id = :serverId and s.name = :name"),
|
||||||
|
@NamedQuery(name="findScopeIdByResourceServer", query="select s.id from ScopeEntity s where s.resourceServer.id = :serverId"),
|
||||||
|
@NamedQuery(name="deleteScopeByResourceServer", query="delete from ScopeEntity s where s.resourceServer.id = :serverId")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
public class ScopeEntity {
|
||||||
|
|
||||||
@Id
|
@Id
|
||||||
@Column(name="ID", length = 36)
|
@Column(name="ID", length = 36)
|
||||||
|
@ -65,7 +74,6 @@ public class ScopeEntity implements Scope {
|
||||||
@JoinTable(name = "SCOPE_POLICY", joinColumns = @JoinColumn(name = "SCOPE_ID"), inverseJoinColumns = @JoinColumn(name = "POLICY_ID"))
|
@JoinTable(name = "SCOPE_POLICY", joinColumns = @JoinColumn(name = "SCOPE_ID"), inverseJoinColumns = @JoinColumn(name = "POLICY_ID"))
|
||||||
private List<PolicyEntity> policies = new ArrayList<>();
|
private List<PolicyEntity> policies = new ArrayList<>();
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
@ -74,33 +82,28 @@ public class ScopeEntity implements Scope {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setName(String name) {
|
public void setName(String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getIconUri() {
|
public String getIconUri() {
|
||||||
return iconUri;
|
return iconUri;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setIconUri(String iconUri) {
|
public void setIconUri(String iconUri) {
|
||||||
this.iconUri = iconUri;
|
this.iconUri = iconUri;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ResourceServerEntity getResourceServer() {
|
public ResourceServerEntity getResourceServer() {
|
||||||
return resourceServer;
|
return resourceServer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<? extends Policy> getPolicies() {
|
public List<PolicyEntity> getPolicies() {
|
||||||
return this.policies;
|
return policies;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPolicies(List<PolicyEntity> policies) {
|
public void setPolicies(List<PolicyEntity> policies) {
|
||||||
|
@ -114,13 +117,15 @@ public class ScopeEntity implements Scope {
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (o == null || !Scope.class.isInstance(o)) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
Scope that = (Scope) o;
|
|
||||||
return Objects.equals(id, that.getId());
|
ScopeEntity that = (ScopeEntity) o;
|
||||||
|
|
||||||
|
return getId().equals(that.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(id);
|
return getId().hashCode();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,8 +32,9 @@ import org.keycloak.models.KeycloakSession;
|
||||||
*/
|
*/
|
||||||
public class JPAAuthorizationStoreFactory implements AuthorizationStoreFactory {
|
public class JPAAuthorizationStoreFactory implements AuthorizationStoreFactory {
|
||||||
@Override
|
@Override
|
||||||
public StoreFactory create(KeycloakSession session) {
|
public StoreFactory create(KeycloakSession session) {
|
||||||
return new JPAStoreFactory(getEntityManager(session));
|
AuthorizationProvider provider = session.getProvider(AuthorizationProvider.class);
|
||||||
|
return new JPAStoreFactory(getEntityManager(session), provider);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -19,23 +19,29 @@ package org.keycloak.authorization.jpa.store;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import javax.persistence.EntityManager;
|
import javax.persistence.EntityManager;
|
||||||
import javax.persistence.NoResultException;
|
import javax.persistence.NoResultException;
|
||||||
import javax.persistence.Query;
|
import javax.persistence.Query;
|
||||||
|
import javax.persistence.TypedQuery;
|
||||||
import javax.persistence.criteria.CriteriaBuilder;
|
import javax.persistence.criteria.CriteriaBuilder;
|
||||||
import javax.persistence.criteria.CriteriaQuery;
|
import javax.persistence.criteria.CriteriaQuery;
|
||||||
import javax.persistence.criteria.Predicate;
|
import javax.persistence.criteria.Predicate;
|
||||||
import javax.persistence.criteria.Root;
|
import javax.persistence.criteria.Root;
|
||||||
|
|
||||||
|
import org.keycloak.authorization.AuthorizationProvider;
|
||||||
import org.keycloak.authorization.jpa.entities.PolicyEntity;
|
import org.keycloak.authorization.jpa.entities.PolicyEntity;
|
||||||
import org.keycloak.authorization.jpa.entities.ResourceServerEntity;
|
import org.keycloak.authorization.jpa.entities.ResourceServerEntity;
|
||||||
import org.keycloak.authorization.model.Policy;
|
import org.keycloak.authorization.model.Policy;
|
||||||
|
import org.keycloak.authorization.model.Resource;
|
||||||
import org.keycloak.authorization.model.ResourceServer;
|
import org.keycloak.authorization.model.ResourceServer;
|
||||||
import org.keycloak.authorization.store.PolicyStore;
|
import org.keycloak.authorization.store.PolicyStore;
|
||||||
|
import org.keycloak.authorization.store.StoreFactory;
|
||||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||||
|
import org.keycloak.models.utils.RepresentationToModel;
|
||||||
import org.keycloak.representations.idm.authorization.AbstractPolicyRepresentation;
|
import org.keycloak.representations.idm.authorization.AbstractPolicyRepresentation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -44,9 +50,10 @@ import org.keycloak.representations.idm.authorization.AbstractPolicyRepresentati
|
||||||
public class JPAPolicyStore implements PolicyStore {
|
public class JPAPolicyStore implements PolicyStore {
|
||||||
|
|
||||||
private final EntityManager entityManager;
|
private final EntityManager entityManager;
|
||||||
|
private final AuthorizationProvider provider;
|
||||||
public JPAPolicyStore(EntityManager entityManager) {
|
public JPAPolicyStore(EntityManager entityManager, AuthorizationProvider provider) {
|
||||||
this.entityManager = entityManager;
|
this.entityManager = entityManager;
|
||||||
|
this.provider = provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -56,17 +63,17 @@ public class JPAPolicyStore implements PolicyStore {
|
||||||
entity.setId(KeycloakModelUtils.generateId());
|
entity.setId(KeycloakModelUtils.generateId());
|
||||||
entity.setType(representation.getType());
|
entity.setType(representation.getType());
|
||||||
entity.setName(representation.getName());
|
entity.setName(representation.getName());
|
||||||
entity.setResourceServer((ResourceServerEntity) resourceServer);
|
entity.setResourceServer(ResourceServerAdapter.toEntity(entityManager, resourceServer));
|
||||||
|
|
||||||
this.entityManager.persist(entity);
|
this.entityManager.persist(entity);
|
||||||
this.entityManager.flush();
|
this.entityManager.flush();
|
||||||
return entity;
|
Policy model = new PolicyAdapter(entity, entityManager, provider.getStoreFactory());
|
||||||
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void delete(String id) {
|
public void delete(String id) {
|
||||||
Policy policy = entityManager.find(PolicyEntity.class, id);
|
PolicyEntity policy = entityManager.find(PolicyEntity.class, id);
|
||||||
|
|
||||||
if (policy != null) {
|
if (policy != null) {
|
||||||
this.entityManager.remove(policy);
|
this.entityManager.remove(policy);
|
||||||
}
|
}
|
||||||
|
@ -79,39 +86,38 @@ public class JPAPolicyStore implements PolicyStore {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resourceServerId == null) {
|
PolicyEntity entity = entityManager.find(PolicyEntity.class, id);
|
||||||
return entityManager.find(PolicyEntity.class, id);
|
if (entity == null) return null;
|
||||||
}
|
|
||||||
|
|
||||||
Query query = entityManager.createQuery("from PolicyEntity where resourceServer.id = :serverId and id = :id");
|
return new PolicyAdapter(entity, entityManager, provider.getStoreFactory());
|
||||||
|
|
||||||
query.setParameter("serverId", resourceServerId);
|
|
||||||
query.setParameter("id", id);
|
|
||||||
|
|
||||||
return entityManager.find(PolicyEntity.class, id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Policy findByName(String name, String resourceServerId) {
|
public Policy findByName(String name, String resourceServerId) {
|
||||||
|
TypedQuery<String> query = entityManager.createNamedQuery("findPolicyIdByName", String.class);
|
||||||
|
|
||||||
|
query.setParameter("serverId", resourceServerId);
|
||||||
|
query.setParameter("name", name);
|
||||||
try {
|
try {
|
||||||
Query query = entityManager.createQuery("from PolicyEntity where name = :name and resourceServer.id = :serverId");
|
String id = query.getSingleResult();
|
||||||
|
return provider.getStoreFactory().getPolicyStore().findById(id, resourceServerId);
|
||||||
query.setParameter("name", name);
|
} catch (NoResultException ex) {
|
||||||
query.setParameter("serverId", resourceServerId);
|
|
||||||
|
|
||||||
return (Policy) query.getSingleResult();
|
|
||||||
} catch (NoResultException nre) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Policy> findByResourceServer(final String resourceServerId) {
|
public List<Policy> findByResourceServer(final String resourceServerId) {
|
||||||
Query query = entityManager.createQuery("from PolicyEntity where resourceServer.id = :serverId");
|
TypedQuery<String> query = entityManager.createNamedQuery("findPolicyIdByServerId", String.class);
|
||||||
|
|
||||||
query.setParameter("serverId", resourceServerId);
|
query.setParameter("serverId", resourceServerId);
|
||||||
|
|
||||||
return query.getResultList();
|
List<String> result = query.getResultList();
|
||||||
|
List<Policy> list = new LinkedList<>();
|
||||||
|
for (String id : result) {
|
||||||
|
list.add(provider.getStoreFactory().getPolicyStore().findById(id, resourceServerId));
|
||||||
|
}
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -120,6 +126,7 @@ public class JPAPolicyStore implements PolicyStore {
|
||||||
CriteriaQuery<PolicyEntity> querybuilder = builder.createQuery(PolicyEntity.class);
|
CriteriaQuery<PolicyEntity> querybuilder = builder.createQuery(PolicyEntity.class);
|
||||||
Root<PolicyEntity> root = querybuilder.from(PolicyEntity.class);
|
Root<PolicyEntity> root = querybuilder.from(PolicyEntity.class);
|
||||||
List<Predicate> predicates = new ArrayList();
|
List<Predicate> predicates = new ArrayList();
|
||||||
|
querybuilder.select(root.get("id"));
|
||||||
|
|
||||||
predicates.add(builder.equal(root.get("resourceServer").get("id"), resourceServerId));
|
predicates.add(builder.equal(root.get("resourceServer").get("id"), resourceServerId));
|
||||||
|
|
||||||
|
@ -148,27 +155,42 @@ public class JPAPolicyStore implements PolicyStore {
|
||||||
query.setMaxResults(maxResult);
|
query.setMaxResults(maxResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
return query.getResultList();
|
List<String> result = query.getResultList();
|
||||||
|
List<Policy> list = new LinkedList<>();
|
||||||
|
for (String id : result) {
|
||||||
|
list.add(provider.getStoreFactory().getPolicyStore().findById(id, resourceServerId));
|
||||||
|
}
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Policy> findByResource(final String resourceId, String resourceServerId) {
|
public List<Policy> findByResource(final String resourceId, String resourceServerId) {
|
||||||
Query query = entityManager.createQuery("select p from PolicyEntity p inner join p.resources r where p.resourceServer.id = :serverId and (r.resourceServer.id = :serverId and r.id = :resourceId)");
|
TypedQuery<String> query = entityManager.createNamedQuery("findPolicyIdByResource", String.class);
|
||||||
|
|
||||||
query.setParameter("resourceId", resourceId);
|
query.setParameter("resourceId", resourceId);
|
||||||
query.setParameter("serverId", resourceServerId);
|
query.setParameter("serverId", resourceServerId);
|
||||||
|
|
||||||
return query.getResultList();
|
List<String> result = query.getResultList();
|
||||||
|
List<Policy> list = new LinkedList<>();
|
||||||
|
for (String id : result) {
|
||||||
|
list.add(provider.getStoreFactory().getPolicyStore().findById(id, resourceServerId));
|
||||||
|
}
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Policy> findByResourceType(final String resourceType, String resourceServerId) {
|
public List<Policy> findByResourceType(final String resourceType, String resourceServerId) {
|
||||||
Query query = entityManager.createQuery("select p from PolicyEntity p inner join p.config c where p.resourceServer.id = :serverId and KEY(c) = 'defaultResourceType' and c like :type");
|
TypedQuery<String> query = entityManager.createNamedQuery("findPolicyIdByResourceType", String.class);
|
||||||
|
|
||||||
query.setParameter("serverId", resourceServerId);
|
|
||||||
query.setParameter("type", resourceType);
|
query.setParameter("type", resourceType);
|
||||||
|
query.setParameter("serverId", resourceServerId);
|
||||||
|
|
||||||
return query.getResultList();
|
List<String> result = query.getResultList();
|
||||||
|
List<Policy> list = new LinkedList<>();
|
||||||
|
for (String id : result) {
|
||||||
|
list.add(provider.getStoreFactory().getPolicyStore().findById(id, resourceServerId));
|
||||||
|
}
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -178,31 +200,47 @@ public class JPAPolicyStore implements PolicyStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use separate subquery to handle DB2 and MSSSQL
|
// Use separate subquery to handle DB2 and MSSSQL
|
||||||
Query query = entityManager.createQuery("select pe from PolicyEntity pe where pe.resourceServer.id = :serverId and pe.id IN (select p.id from ScopeEntity s inner join s.policies p where s.resourceServer.id = :serverId and (p.resourceServer.id = :serverId and p.type = 'scope' and s.id in (:scopeIds)))");
|
TypedQuery<String> query = entityManager.createNamedQuery("findPolicyIdByScope", String.class);
|
||||||
|
|
||||||
query.setParameter("serverId", resourceServerId);
|
|
||||||
query.setParameter("scopeIds", scopeIds);
|
query.setParameter("scopeIds", scopeIds);
|
||||||
|
query.setParameter("serverId", resourceServerId);
|
||||||
|
|
||||||
return query.getResultList();
|
List<String> result = query.getResultList();
|
||||||
|
List<Policy> list = new LinkedList<>();
|
||||||
|
for (String id : result) {
|
||||||
|
list.add(provider.getStoreFactory().getPolicyStore().findById(id, resourceServerId));
|
||||||
|
}
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Policy> findByType(String type, String resourceServerId) {
|
public List<Policy> findByType(String type, String resourceServerId) {
|
||||||
Query query = entityManager.createQuery("select p from PolicyEntity p where p.resourceServer.id = :serverId and p.type = :type");
|
TypedQuery<String> query = entityManager.createNamedQuery("findPolicyIdByType", String.class);
|
||||||
|
|
||||||
query.setParameter("serverId", resourceServerId);
|
query.setParameter("serverId", resourceServerId);
|
||||||
query.setParameter("type", type);
|
query.setParameter("type", type);
|
||||||
|
|
||||||
return query.getResultList();
|
List<String> result = query.getResultList();
|
||||||
|
List<Policy> list = new LinkedList<>();
|
||||||
|
for (String id : result) {
|
||||||
|
list.add(provider.getStoreFactory().getPolicyStore().findById(id, resourceServerId));
|
||||||
|
}
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Policy> findDependentPolicies(String policyId, String resourceServerId) {
|
public List<Policy> findDependentPolicies(String policyId, String resourceServerId) {
|
||||||
Query query = entityManager.createQuery("select p from PolicyEntity p inner join p.associatedPolicies ap where p.resourceServer.id = :serverId and (ap.resourceServer.id = :serverId and ap.id = :policyId)");
|
|
||||||
|
TypedQuery<String> query = entityManager.createNamedQuery("findPolicyIdByDependentPolices", String.class);
|
||||||
|
|
||||||
query.setParameter("serverId", resourceServerId);
|
query.setParameter("serverId", resourceServerId);
|
||||||
query.setParameter("policyId", policyId);
|
query.setParameter("policyId", policyId);
|
||||||
|
|
||||||
return query.getResultList();
|
List<String> result = query.getResultList();
|
||||||
|
List<Policy> list = new LinkedList<>();
|
||||||
|
for (String id : result) {
|
||||||
|
list.add(provider.getStoreFactory().getPolicyStore().findById(id, resourceServerId));
|
||||||
|
}
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,13 +17,19 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.authorization.jpa.store;
|
package org.keycloak.authorization.jpa.store;
|
||||||
|
|
||||||
|
import org.keycloak.authorization.AuthorizationProvider;
|
||||||
|
import org.keycloak.authorization.jpa.entities.PolicyEntity;
|
||||||
import org.keycloak.authorization.jpa.entities.ResourceServerEntity;
|
import org.keycloak.authorization.jpa.entities.ResourceServerEntity;
|
||||||
|
import org.keycloak.authorization.model.Policy;
|
||||||
import org.keycloak.authorization.model.ResourceServer;
|
import org.keycloak.authorization.model.ResourceServer;
|
||||||
import org.keycloak.authorization.store.ResourceServerStore;
|
import org.keycloak.authorization.store.ResourceServerStore;
|
||||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||||
|
|
||||||
import javax.persistence.EntityManager;
|
import javax.persistence.EntityManager;
|
||||||
|
import javax.persistence.NoResultException;
|
||||||
import javax.persistence.Query;
|
import javax.persistence.Query;
|
||||||
|
import javax.persistence.TypedQuery;
|
||||||
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -32,9 +38,11 @@ import java.util.List;
|
||||||
public class JPAResourceServerStore implements ResourceServerStore {
|
public class JPAResourceServerStore implements ResourceServerStore {
|
||||||
|
|
||||||
private final EntityManager entityManager;
|
private final EntityManager entityManager;
|
||||||
|
private final AuthorizationProvider provider;
|
||||||
|
|
||||||
public JPAResourceServerStore(EntityManager entityManager) {
|
public JPAResourceServerStore(EntityManager entityManager, AuthorizationProvider provider) {
|
||||||
this.entityManager = entityManager;
|
this.entityManager = entityManager;
|
||||||
|
this.provider = provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -46,30 +54,54 @@ public class JPAResourceServerStore implements ResourceServerStore {
|
||||||
|
|
||||||
this.entityManager.persist(entity);
|
this.entityManager.persist(entity);
|
||||||
|
|
||||||
return entity;
|
return new ResourceServerAdapter(entity, entityManager, provider.getStoreFactory());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void delete(String id) {
|
public void delete(String id) {
|
||||||
this.entityManager.remove(findById(id));
|
ResourceServerEntity entity = entityManager.find(ResourceServerEntity.class, id);
|
||||||
|
if (entity == null) return;
|
||||||
|
//This didn't work, had to loop through and remove each policy individually
|
||||||
|
//entityManager.createNamedQuery("deletePolicyByResourceServer")
|
||||||
|
// .setParameter("serverId", id).executeUpdate();
|
||||||
|
|
||||||
|
TypedQuery<String> query = entityManager.createNamedQuery("findPolicyIdByServerId", String.class);
|
||||||
|
query.setParameter("serverId", id);
|
||||||
|
List<String> result = query.getResultList();
|
||||||
|
List<Policy> list = new LinkedList<>();
|
||||||
|
for (String policyId : result) {
|
||||||
|
entityManager.remove(entityManager.getReference(PolicyEntity.class, policyId));
|
||||||
|
}
|
||||||
|
|
||||||
|
entityManager.flush();
|
||||||
|
entityManager.createNamedQuery("deleteResourceByResourceServer")
|
||||||
|
.setParameter("serverId", id).executeUpdate();
|
||||||
|
entityManager.flush();
|
||||||
|
entityManager.createNamedQuery("deleteScopeByResourceServer")
|
||||||
|
.setParameter("serverId", id).executeUpdate();
|
||||||
|
entityManager.flush();
|
||||||
|
|
||||||
|
this.entityManager.remove(entity);
|
||||||
|
entityManager.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResourceServer findById(String id) {
|
public ResourceServer findById(String id) {
|
||||||
return entityManager.find(ResourceServerEntity.class, id);
|
ResourceServerEntity entity = entityManager.find(ResourceServerEntity.class, id);
|
||||||
|
if (entity == null) return null;
|
||||||
|
return new ResourceServerAdapter(entity, entityManager, provider.getStoreFactory());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResourceServer findByClient(final String clientId) {
|
public ResourceServer findByClient(final String clientId) {
|
||||||
Query query = entityManager.createQuery("from ResourceServerEntity where clientId = :clientId");
|
TypedQuery<String> query = entityManager.createNamedQuery("findResourceServerIdByClient", String.class);
|
||||||
|
|
||||||
query.setParameter("clientId", clientId);
|
query.setParameter("clientId", clientId);
|
||||||
List result = query.getResultList();
|
try {
|
||||||
|
String id = query.getSingleResult();
|
||||||
if (result.isEmpty()) {
|
return provider.getStoreFactory().getResourceServerStore().findById(id);
|
||||||
|
} catch (NoResultException ex) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (ResourceServer) result.get(0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.authorization.jpa.store;
|
package org.keycloak.authorization.jpa.store;
|
||||||
|
|
||||||
|
import org.keycloak.authorization.AuthorizationProvider;
|
||||||
import org.keycloak.authorization.jpa.entities.ResourceEntity;
|
import org.keycloak.authorization.jpa.entities.ResourceEntity;
|
||||||
import org.keycloak.authorization.jpa.entities.ResourceServerEntity;
|
import org.keycloak.authorization.jpa.entities.ResourceServerEntity;
|
||||||
import org.keycloak.authorization.model.Resource;
|
import org.keycloak.authorization.model.Resource;
|
||||||
|
@ -25,13 +26,16 @@ import org.keycloak.authorization.store.ResourceStore;
|
||||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||||
|
|
||||||
import javax.persistence.EntityManager;
|
import javax.persistence.EntityManager;
|
||||||
|
import javax.persistence.NoResultException;
|
||||||
import javax.persistence.Query;
|
import javax.persistence.Query;
|
||||||
|
import javax.persistence.TypedQuery;
|
||||||
import javax.persistence.criteria.CriteriaBuilder;
|
import javax.persistence.criteria.CriteriaBuilder;
|
||||||
import javax.persistence.criteria.CriteriaQuery;
|
import javax.persistence.criteria.CriteriaQuery;
|
||||||
import javax.persistence.criteria.Predicate;
|
import javax.persistence.criteria.Predicate;
|
||||||
import javax.persistence.criteria.Root;
|
import javax.persistence.criteria.Root;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ -41,38 +45,34 @@ import java.util.Map;
|
||||||
public class JPAResourceStore implements ResourceStore {
|
public class JPAResourceStore implements ResourceStore {
|
||||||
|
|
||||||
private final EntityManager entityManager;
|
private final EntityManager entityManager;
|
||||||
|
private final AuthorizationProvider provider;
|
||||||
|
|
||||||
public JPAResourceStore(EntityManager entityManager) {
|
public JPAResourceStore(EntityManager entityManager, AuthorizationProvider provider) {
|
||||||
this.entityManager = entityManager;
|
this.entityManager = entityManager;
|
||||||
|
this.provider = provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Resource create(String name, ResourceServer resourceServer, String owner) {
|
public Resource create(String name, ResourceServer resourceServer, String owner) {
|
||||||
if (!(resourceServer instanceof ResourceServerEntity)) {
|
|
||||||
throw new RuntimeException("Unexpected type [" + resourceServer.getClass() + "].");
|
|
||||||
}
|
|
||||||
|
|
||||||
ResourceEntity entity = new ResourceEntity();
|
ResourceEntity entity = new ResourceEntity();
|
||||||
|
|
||||||
entity.setId(KeycloakModelUtils.generateId());
|
entity.setId(KeycloakModelUtils.generateId());
|
||||||
entity.setName(name);
|
entity.setName(name);
|
||||||
entity.setResourceServer((ResourceServerEntity) resourceServer);
|
entity.setResourceServer(ResourceServerAdapter.toEntity(entityManager, resourceServer));
|
||||||
entity.setOwner(owner);
|
entity.setOwner(owner);
|
||||||
|
|
||||||
this.entityManager.persist(entity);
|
this.entityManager.persist(entity);
|
||||||
|
|
||||||
return entity;
|
return new ResourceAdapter(entity, entityManager, provider.getStoreFactory());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void delete(String id) {
|
public void delete(String id) {
|
||||||
Resource resource = entityManager.find(ResourceEntity.class, id);
|
ResourceEntity resource = entityManager.find(ResourceEntity.class, id);
|
||||||
|
if (resource == null) return;
|
||||||
|
|
||||||
resource.getScopes().clear();
|
resource.getScopes().clear();
|
||||||
|
this.entityManager.remove(resource);
|
||||||
if (resource != null) {
|
|
||||||
this.entityManager.remove(resource);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -81,52 +81,61 @@ public class JPAResourceStore implements ResourceStore {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resourceServerId == null) {
|
ResourceEntity entity = entityManager.find(ResourceEntity.class, id);
|
||||||
return entityManager.find(ResourceEntity.class, id);
|
if (entity == null) return null;
|
||||||
}
|
return new ResourceAdapter(entity, entityManager, provider.getStoreFactory());
|
||||||
|
|
||||||
Query query = entityManager.createQuery("from ResourceEntity where resourceServer.id = :serverId and id = :id");
|
|
||||||
|
|
||||||
query.setParameter("serverId", resourceServerId);
|
|
||||||
query.setParameter("id", id);
|
|
||||||
|
|
||||||
return entityManager.find(ResourceEntity.class, id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Resource> findByOwner(String ownerId, String resourceServerId) {
|
public List<Resource> findByOwner(String ownerId, String resourceServerId) {
|
||||||
Query query = entityManager.createQuery("from ResourceEntity where resourceServer.id = :serverId and owner = :ownerId");
|
TypedQuery<String> query = entityManager.createNamedQuery("findResourceIdByOwner", String.class);
|
||||||
|
|
||||||
query.setParameter("ownerId", ownerId);
|
query.setParameter("owner", ownerId);
|
||||||
query.setParameter("serverId", resourceServerId);
|
query.setParameter("serverId", resourceServerId);
|
||||||
|
|
||||||
return query.getResultList();
|
List<String> result = query.getResultList();
|
||||||
|
List<Resource> list = new LinkedList<>();
|
||||||
|
for (String id : result) {
|
||||||
|
list.add(provider.getStoreFactory().getResourceStore().findById(id, resourceServerId));
|
||||||
|
}
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Resource> findByUri(String uri, String resourceServerId) {
|
public List<Resource> findByUri(String uri, String resourceServerId) {
|
||||||
Query query = entityManager.createQuery("from ResourceEntity where resourceServer.id = :serverId and uri = :uri");
|
TypedQuery<String> query = entityManager.createNamedQuery("findResourceIdByUri", String.class);
|
||||||
|
|
||||||
query.setParameter("uri", uri);
|
query.setParameter("uri", uri);
|
||||||
query.setParameter("serverId", resourceServerId);
|
query.setParameter("serverId", resourceServerId);
|
||||||
|
|
||||||
return query.getResultList();
|
List<String> result = query.getResultList();
|
||||||
|
List<Resource> list = new LinkedList<>();
|
||||||
|
for (String id : result) {
|
||||||
|
list.add(provider.getStoreFactory().getResourceStore().findById(id, resourceServerId));
|
||||||
|
}
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List findByResourceServer(String resourceServerId) {
|
public List<Resource> findByResourceServer(String resourceServerId) {
|
||||||
Query query = entityManager.createQuery("from ResourceEntity where resourceServer.id = :serverId");
|
TypedQuery<String> query = entityManager.createNamedQuery("findResourceIdByServerId", String.class);
|
||||||
|
|
||||||
query.setParameter("serverId", resourceServerId);
|
query.setParameter("serverId", resourceServerId);
|
||||||
|
|
||||||
return query.getResultList();
|
List<String> result = query.getResultList();
|
||||||
|
List<Resource> list = new LinkedList<>();
|
||||||
|
for (String id : result) {
|
||||||
|
list.add(provider.getStoreFactory().getResourceStore().findById(id, resourceServerId));
|
||||||
|
}
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List findByResourceServer(Map<String, String[]> attributes, String resourceServerId, int firstResult, int maxResult) {
|
public List<Resource> findByResourceServer(Map<String, String[]> attributes, String resourceServerId, int firstResult, int maxResult) {
|
||||||
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
|
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
|
||||||
CriteriaQuery<ResourceEntity> querybuilder = builder.createQuery(ResourceEntity.class);
|
CriteriaQuery<ResourceEntity> querybuilder = builder.createQuery(ResourceEntity.class);
|
||||||
Root<ResourceEntity> root = querybuilder.from(ResourceEntity.class);
|
Root<ResourceEntity> root = querybuilder.from(ResourceEntity.class);
|
||||||
|
querybuilder.select(root.get("id"));
|
||||||
List<Predicate> predicates = new ArrayList();
|
List<Predicate> predicates = new ArrayList();
|
||||||
|
|
||||||
predicates.add(builder.equal(root.get("resourceServer").get("id"), resourceServerId));
|
predicates.add(builder.equal(root.get("resourceServer").get("id"), resourceServerId));
|
||||||
|
@ -152,42 +161,55 @@ public class JPAResourceStore implements ResourceStore {
|
||||||
query.setMaxResults(maxResult);
|
query.setMaxResults(maxResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
return query.getResultList();
|
List<String> result = query.getResultList();
|
||||||
|
List<Resource> list = new LinkedList<>();
|
||||||
|
for (String id : result) {
|
||||||
|
list.add(provider.getStoreFactory().getResourceStore().findById(id, resourceServerId));
|
||||||
|
}
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Resource> findByScope(List<String> id, String resourceServerId) {
|
public List<Resource> findByScope(List<String> scopes, String resourceServerId) {
|
||||||
Query query = entityManager.createQuery("select r from ResourceEntity r inner join r.scopes s where r.resourceServer.id = :serverId and (s.resourceServer.id = :serverId and s.id in (:scopeIds))");
|
TypedQuery<String> query = entityManager.createNamedQuery("findResourceIdByScope", String.class);
|
||||||
|
|
||||||
query.setParameter("scopeIds", id);
|
query.setParameter("scopeIds", scopes);
|
||||||
query.setParameter("serverId", resourceServerId);
|
query.setParameter("serverId", resourceServerId);
|
||||||
|
|
||||||
return query.getResultList();
|
List<String> result = query.getResultList();
|
||||||
|
List<Resource> list = new LinkedList<>();
|
||||||
|
for (String id : result) {
|
||||||
|
list.add(provider.getStoreFactory().getResourceStore().findById(id, resourceServerId));
|
||||||
|
}
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Resource findByName(String name, String resourceServerId) {
|
public Resource findByName(String name, String resourceServerId) {
|
||||||
Query query = entityManager.createQuery("from ResourceEntity where resourceServer.id = :serverId and name = :name");
|
TypedQuery<String> query = entityManager.createNamedQuery("findResourceIdByName", String.class);
|
||||||
|
|
||||||
query.setParameter("serverId", resourceServerId);
|
query.setParameter("serverId", resourceServerId);
|
||||||
query.setParameter("name", name);
|
query.setParameter("name", name);
|
||||||
|
try {
|
||||||
List<Resource> result = query.getResultList();
|
String id = query.getSingleResult();
|
||||||
|
return provider.getStoreFactory().getResourceStore().findById(id, resourceServerId);
|
||||||
if (!result.isEmpty()) {
|
} catch (NoResultException ex) {
|
||||||
return result.get(0);
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Resource> findByType(String type, String resourceServerId) {
|
public List<Resource> findByType(String type, String resourceServerId) {
|
||||||
Query query = entityManager.createQuery("from ResourceEntity r where r.resourceServer.id = :serverId and type = :type");
|
TypedQuery<String> query = entityManager.createNamedQuery("findResourceIdByType", String.class);
|
||||||
|
|
||||||
query.setParameter("type", type);
|
query.setParameter("type", type);
|
||||||
query.setParameter("serverId", resourceServerId);
|
query.setParameter("serverId", resourceServerId);
|
||||||
|
|
||||||
return query.getResultList();
|
List<String> result = query.getResultList();
|
||||||
|
List<Resource> list = new LinkedList<>();
|
||||||
|
for (String id : result) {
|
||||||
|
list.add(provider.getStoreFactory().getResourceStore().findById(id, resourceServerId));
|
||||||
|
}
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,17 +18,20 @@
|
||||||
package org.keycloak.authorization.jpa.store;
|
package org.keycloak.authorization.jpa.store;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import javax.persistence.EntityManager;
|
import javax.persistence.EntityManager;
|
||||||
import javax.persistence.NoResultException;
|
import javax.persistence.NoResultException;
|
||||||
import javax.persistence.Query;
|
import javax.persistence.Query;
|
||||||
|
import javax.persistence.TypedQuery;
|
||||||
import javax.persistence.criteria.CriteriaBuilder;
|
import javax.persistence.criteria.CriteriaBuilder;
|
||||||
import javax.persistence.criteria.CriteriaQuery;
|
import javax.persistence.criteria.CriteriaQuery;
|
||||||
import javax.persistence.criteria.Predicate;
|
import javax.persistence.criteria.Predicate;
|
||||||
import javax.persistence.criteria.Root;
|
import javax.persistence.criteria.Root;
|
||||||
|
|
||||||
|
import org.keycloak.authorization.AuthorizationProvider;
|
||||||
import org.keycloak.authorization.jpa.entities.ResourceServerEntity;
|
import org.keycloak.authorization.jpa.entities.ResourceServerEntity;
|
||||||
import org.keycloak.authorization.jpa.entities.ScopeEntity;
|
import org.keycloak.authorization.jpa.entities.ScopeEntity;
|
||||||
import org.keycloak.authorization.model.ResourceServer;
|
import org.keycloak.authorization.model.ResourceServer;
|
||||||
|
@ -42,9 +45,11 @@ import org.keycloak.models.utils.KeycloakModelUtils;
|
||||||
public class JPAScopeStore implements ScopeStore {
|
public class JPAScopeStore implements ScopeStore {
|
||||||
|
|
||||||
private final EntityManager entityManager;
|
private final EntityManager entityManager;
|
||||||
|
private final AuthorizationProvider provider;
|
||||||
|
|
||||||
public JPAScopeStore(EntityManager entityManager) {
|
public JPAScopeStore(EntityManager entityManager, AuthorizationProvider provider) {
|
||||||
this.entityManager = entityManager;
|
this.entityManager = entityManager;
|
||||||
|
this.provider = provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -53,16 +58,16 @@ public class JPAScopeStore implements ScopeStore {
|
||||||
|
|
||||||
entity.setId(KeycloakModelUtils.generateId());
|
entity.setId(KeycloakModelUtils.generateId());
|
||||||
entity.setName(name);
|
entity.setName(name);
|
||||||
entity.setResourceServer((ResourceServerEntity) resourceServer);
|
entity.setResourceServer(ResourceServerAdapter.toEntity(entityManager, resourceServer));
|
||||||
|
|
||||||
this.entityManager.persist(entity);
|
this.entityManager.persist(entity);
|
||||||
|
|
||||||
return entity;
|
return new ScopeAdapter(entity, entityManager, provider.getStoreFactory());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void delete(String id) {
|
public void delete(String id) {
|
||||||
Scope scope = entityManager.find(ScopeEntity.class, id);
|
ScopeEntity scope = entityManager.find(ScopeEntity.class, id);
|
||||||
|
|
||||||
if (scope != null) {
|
if (scope != null) {
|
||||||
this.entityManager.remove(scope);
|
this.entityManager.remove(scope);
|
||||||
|
@ -75,28 +80,21 @@ public class JPAScopeStore implements ScopeStore {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resourceServerId == null) {
|
ScopeEntity entity = entityManager.find(ScopeEntity.class, id);
|
||||||
return entityManager.find(ScopeEntity.class, id);
|
if (entity == null) return null;
|
||||||
}
|
|
||||||
|
|
||||||
Query query = entityManager.createQuery("from ScopeEntity where resourceServer.id = :serverId and id = :id");
|
|
||||||
|
|
||||||
query.setParameter("serverId", resourceServerId);
|
|
||||||
query.setParameter("id", id);
|
|
||||||
|
|
||||||
return entityManager.find(ScopeEntity.class, id);
|
|
||||||
|
|
||||||
|
return new ScopeAdapter(entity, entityManager, provider.getStoreFactory());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Scope findByName(String name, String resourceServerId) {
|
public Scope findByName(String name, String resourceServerId) {
|
||||||
try {
|
try {
|
||||||
Query query = entityManager.createQuery("select s from ScopeEntity s inner join s.resourceServer rs where rs.id = :resourceServerId and name = :name");
|
TypedQuery<String> query = entityManager.createNamedQuery("findScopeIdByName", String.class);
|
||||||
|
|
||||||
query.setParameter("resourceServerId", resourceServerId);
|
query.setParameter("serverId", resourceServerId);
|
||||||
query.setParameter("name", name);
|
query.setParameter("name", name);
|
||||||
|
String id = query.getSingleResult();
|
||||||
return (Scope) query.getSingleResult();
|
return provider.getStoreFactory().getScopeStore().findById(id, resourceServerId);
|
||||||
} catch (NoResultException nre) {
|
} catch (NoResultException nre) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -104,11 +102,16 @@ public class JPAScopeStore implements ScopeStore {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Scope> findByResourceServer(final String serverId) {
|
public List<Scope> findByResourceServer(final String serverId) {
|
||||||
Query query = entityManager.createQuery("from ScopeEntity where resourceServer.id = :serverId");
|
TypedQuery<String> query = entityManager.createNamedQuery("findScopeIdByResourceServer", String.class);
|
||||||
|
|
||||||
query.setParameter("serverId", serverId);
|
query.setParameter("serverId", serverId);
|
||||||
|
|
||||||
return query.getResultList();
|
List<String> result = query.getResultList();
|
||||||
|
List<Scope> list = new LinkedList<>();
|
||||||
|
for (String id : result) {
|
||||||
|
list.add(provider.getStoreFactory().getScopeStore().findById(id, serverId));
|
||||||
|
}
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -116,6 +119,7 @@ public class JPAScopeStore implements ScopeStore {
|
||||||
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
|
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
|
||||||
CriteriaQuery<ScopeEntity> querybuilder = builder.createQuery(ScopeEntity.class);
|
CriteriaQuery<ScopeEntity> querybuilder = builder.createQuery(ScopeEntity.class);
|
||||||
Root<ScopeEntity> root = querybuilder.from(ScopeEntity.class);
|
Root<ScopeEntity> root = querybuilder.from(ScopeEntity.class);
|
||||||
|
querybuilder.select(root.get("id"));
|
||||||
List<Predicate> predicates = new ArrayList();
|
List<Predicate> predicates = new ArrayList();
|
||||||
|
|
||||||
predicates.add(builder.equal(root.get("resourceServer").get("id"), resourceServerId));
|
predicates.add(builder.equal(root.get("resourceServer").get("id"), resourceServerId));
|
||||||
|
@ -139,6 +143,12 @@ public class JPAScopeStore implements ScopeStore {
|
||||||
query.setMaxResults(maxResult);
|
query.setMaxResults(maxResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
return query.getResultList();
|
List result = query.getResultList();
|
||||||
|
List<Scope> list = new LinkedList<>();
|
||||||
|
for (Object id : result) {
|
||||||
|
list.add(provider.getStoreFactory().getScopeStore().findById((String)id, resourceServerId));
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ package org.keycloak.authorization.jpa.store;
|
||||||
|
|
||||||
import javax.persistence.EntityManager;
|
import javax.persistence.EntityManager;
|
||||||
|
|
||||||
|
import org.keycloak.authorization.AuthorizationProvider;
|
||||||
import org.keycloak.authorization.store.PolicyStore;
|
import org.keycloak.authorization.store.PolicyStore;
|
||||||
import org.keycloak.authorization.store.ResourceServerStore;
|
import org.keycloak.authorization.store.ResourceServerStore;
|
||||||
import org.keycloak.authorization.store.ResourceStore;
|
import org.keycloak.authorization.store.ResourceStore;
|
||||||
|
@ -36,11 +37,11 @@ public class JPAStoreFactory implements StoreFactory {
|
||||||
private final ResourceStore resourceStore;
|
private final ResourceStore resourceStore;
|
||||||
private final ScopeStore scopeStore;
|
private final ScopeStore scopeStore;
|
||||||
|
|
||||||
public JPAStoreFactory(EntityManager entityManager) {
|
public JPAStoreFactory(EntityManager entityManager, AuthorizationProvider provider) {
|
||||||
policyStore = new JPAPolicyStore(entityManager);
|
policyStore = new JPAPolicyStore(entityManager, provider);
|
||||||
resourceServerStore = new JPAResourceServerStore(entityManager);
|
resourceServerStore = new JPAResourceServerStore(entityManager, provider);
|
||||||
resourceStore = new JPAResourceStore(entityManager);
|
resourceStore = new JPAResourceStore(entityManager, provider);
|
||||||
scopeStore = new JPAScopeStore(entityManager);
|
scopeStore = new JPAScopeStore(entityManager, provider);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -0,0 +1,235 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||||
|
* and other contributors as indicated by the @author tags.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.keycloak.authorization.jpa.store;
|
||||||
|
|
||||||
|
import org.keycloak.authorization.AuthorizationProvider;
|
||||||
|
import org.keycloak.authorization.jpa.entities.PolicyEntity;
|
||||||
|
import org.keycloak.authorization.jpa.entities.ResourceEntity;
|
||||||
|
import org.keycloak.authorization.jpa.entities.ScopeEntity;
|
||||||
|
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.store.StoreFactory;
|
||||||
|
import org.keycloak.models.jpa.JpaModel;
|
||||||
|
import org.keycloak.representations.idm.authorization.DecisionStrategy;
|
||||||
|
import org.keycloak.representations.idm.authorization.Logic;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class PolicyAdapter implements Policy, JpaModel<PolicyEntity> {
|
||||||
|
private PolicyEntity entity;
|
||||||
|
private EntityManager em;
|
||||||
|
private StoreFactory storeFactory;
|
||||||
|
|
||||||
|
public PolicyAdapter(PolicyEntity entity, EntityManager em, StoreFactory storeFactory) {
|
||||||
|
this.entity = entity;
|
||||||
|
this.em = em;
|
||||||
|
this.storeFactory = storeFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PolicyEntity getEntity() {
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return entity.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getType() {
|
||||||
|
return entity.getType();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DecisionStrategy getDecisionStrategy() {
|
||||||
|
return entity.getDecisionStrategy();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setDecisionStrategy(DecisionStrategy decisionStrategy) {
|
||||||
|
entity.setDecisionStrategy(decisionStrategy);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Logic getLogic() {
|
||||||
|
return entity.getLogic();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setLogic(Logic logic) {
|
||||||
|
entity.setLogic(logic);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> getConfig() {
|
||||||
|
Map<String, String> result = new HashMap<String, String>();
|
||||||
|
if (entity.getConfig() != null) result.putAll(entity.getConfig());
|
||||||
|
return Collections.unmodifiableMap(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setConfig(Map<String, String> config) {
|
||||||
|
if (entity.getConfig() == null) {
|
||||||
|
entity.setConfig(new HashMap<>());
|
||||||
|
} else {
|
||||||
|
entity.getConfig().clear();
|
||||||
|
}
|
||||||
|
entity.getConfig().putAll(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeConfig(String name) {
|
||||||
|
if (entity.getConfig() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
entity.getConfig().remove(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void putConfig(String name, String value) {
|
||||||
|
if (entity.getConfig() == null) {
|
||||||
|
entity.setConfig(new HashMap<>());
|
||||||
|
}
|
||||||
|
entity.getConfig().put(name, value);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return entity.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setName(String name) {
|
||||||
|
entity.setName(name);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDescription() {
|
||||||
|
return entity.getDescription();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setDescription(String description) {
|
||||||
|
entity.setDescription(description);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResourceServer getResourceServer() {
|
||||||
|
return storeFactory.getResourceServerStore().findById(entity.getResourceServer().getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<Policy> getAssociatedPolicies() {
|
||||||
|
Set<Policy> result = new HashSet<>();
|
||||||
|
for (PolicyEntity policy : entity.getAssociatedPolicies()) {
|
||||||
|
Policy p = storeFactory.getPolicyStore().findById(policy.getId(), entity.getResourceServer().getId());
|
||||||
|
result.add(p);
|
||||||
|
}
|
||||||
|
return Collections.unmodifiableSet(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<Resource> getResources() {
|
||||||
|
Set<Resource> set = new HashSet<>();
|
||||||
|
for (ResourceEntity res : entity.getResources()) {
|
||||||
|
set.add(storeFactory.getResourceStore().findById(res.getId(), entity.getResourceServer().getId()));
|
||||||
|
}
|
||||||
|
return Collections.unmodifiableSet(set);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<Scope> getScopes() {
|
||||||
|
Set<Scope> set = new HashSet<>();
|
||||||
|
for (ScopeEntity res : entity.getScopes()) {
|
||||||
|
set.add(storeFactory.getScopeStore().findById(res.getId(), entity.getResourceServer().getId()));
|
||||||
|
}
|
||||||
|
return Collections.unmodifiableSet(set);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addScope(Scope scope) {
|
||||||
|
entity.getScopes().add(ScopeAdapter.toEntity(em, scope));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeScope(Scope scope) {
|
||||||
|
entity.getScopes().remove(ScopeAdapter.toEntity(em, scope));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addAssociatedPolicy(Policy associatedPolicy) {
|
||||||
|
entity.getAssociatedPolicies().add(toEntity(em, associatedPolicy));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeAssociatedPolicy(Policy associatedPolicy) {
|
||||||
|
entity.getAssociatedPolicies().remove(toEntity(em, associatedPolicy));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addResource(Resource resource) {
|
||||||
|
entity.getResources().add(ResourceAdapter.toEntity(em, resource));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeResource(Resource resource) {
|
||||||
|
entity.getResources().remove(ResourceAdapter.toEntity(em, resource));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || !(o instanceof Policy)) return false;
|
||||||
|
|
||||||
|
Policy that = (Policy) o;
|
||||||
|
return that.getId().equals(getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return getId().hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PolicyEntity toEntity(EntityManager em, Policy policy) {
|
||||||
|
if (policy instanceof PolicyAdapter) {
|
||||||
|
return ((PolicyAdapter)policy).getEntity();
|
||||||
|
} else {
|
||||||
|
return em.getReference(PolicyEntity.class, policy.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,166 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||||
|
* and other contributors as indicated by the @author tags.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.keycloak.authorization.jpa.store;
|
||||||
|
|
||||||
|
import org.keycloak.authorization.AuthorizationProvider;
|
||||||
|
import org.keycloak.authorization.jpa.entities.ResourceEntity;
|
||||||
|
import org.keycloak.authorization.jpa.entities.ScopeEntity;
|
||||||
|
import org.keycloak.authorization.model.Resource;
|
||||||
|
import org.keycloak.authorization.model.ResourceServer;
|
||||||
|
import org.keycloak.authorization.model.Scope;
|
||||||
|
import org.keycloak.authorization.store.StoreFactory;
|
||||||
|
import org.keycloak.models.jpa.JpaModel;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class ResourceAdapter implements Resource, JpaModel<ResourceEntity> {
|
||||||
|
private ResourceEntity entity;
|
||||||
|
private EntityManager em;
|
||||||
|
private StoreFactory storeFactory;
|
||||||
|
|
||||||
|
public ResourceAdapter(ResourceEntity entity, EntityManager em, StoreFactory storeFactory) {
|
||||||
|
this.entity = entity;
|
||||||
|
this.em = em;
|
||||||
|
this.storeFactory = storeFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResourceEntity getEntity() {
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return entity.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return entity.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setName(String name) {
|
||||||
|
entity.setName(name);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUri() {
|
||||||
|
return entity.getUri();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setUri(String uri) {
|
||||||
|
entity.setUri(uri);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getType() {
|
||||||
|
return entity.getType();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setType(String type) {
|
||||||
|
entity.setType(type);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Scope> getScopes() {
|
||||||
|
List<Scope> scopes = new LinkedList<>();
|
||||||
|
for (ScopeEntity scope : entity.getScopes()) {
|
||||||
|
scopes.add(storeFactory.getScopeStore().findById(scope.getId(), entity.getResourceServer().getId()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return Collections.unmodifiableList(scopes);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getIconUri() {
|
||||||
|
return entity.getIconUri();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setIconUri(String iconUri) {
|
||||||
|
entity.setIconUri(iconUri);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResourceServer getResourceServer() {
|
||||||
|
return storeFactory.getResourceServerStore().findById(entity.getResourceServer().getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getOwner() {
|
||||||
|
return entity.getOwner();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateScopes(Set<Scope> toUpdate) {
|
||||||
|
Set<String> ids = new HashSet<>();
|
||||||
|
for (Scope scope : toUpdate) {
|
||||||
|
ids.add(scope.getId());
|
||||||
|
}
|
||||||
|
Iterator<ScopeEntity> it = entity.getScopes().iterator();
|
||||||
|
while (it.hasNext()) {
|
||||||
|
ScopeEntity next = it.next();
|
||||||
|
if (!ids.contains(next.getId())) it.remove();
|
||||||
|
else ids.remove(next.getId());
|
||||||
|
}
|
||||||
|
for (String addId : ids) {
|
||||||
|
entity.getScopes().add(em.getReference(ScopeEntity.class, addId));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static ResourceEntity toEntity(EntityManager em, Resource resource) {
|
||||||
|
if (resource instanceof ResourceAdapter) {
|
||||||
|
return ((ResourceAdapter)resource).getEntity();
|
||||||
|
} else {
|
||||||
|
return em.getReference(ResourceEntity.class, resource.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || !(o instanceof Resource)) return false;
|
||||||
|
|
||||||
|
Resource that = (Resource) o;
|
||||||
|
return that.getId().equals(getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return getId().hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,106 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||||
|
* and other contributors as indicated by the @author tags.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.keycloak.authorization.jpa.store;
|
||||||
|
|
||||||
|
import org.keycloak.authorization.AuthorizationProvider;
|
||||||
|
import org.keycloak.authorization.jpa.entities.ResourceEntity;
|
||||||
|
import org.keycloak.authorization.jpa.entities.ResourceServerEntity;
|
||||||
|
import org.keycloak.authorization.model.Policy;
|
||||||
|
import org.keycloak.authorization.model.Resource;
|
||||||
|
import org.keycloak.authorization.model.ResourceServer;
|
||||||
|
import org.keycloak.authorization.store.StoreFactory;
|
||||||
|
import org.keycloak.models.jpa.JpaModel;
|
||||||
|
import org.keycloak.representations.idm.authorization.PolicyEnforcementMode;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class ResourceServerAdapter implements ResourceServer, JpaModel<ResourceServerEntity> {
|
||||||
|
private ResourceServerEntity entity;
|
||||||
|
private EntityManager em;
|
||||||
|
private StoreFactory storeFactory;
|
||||||
|
|
||||||
|
public ResourceServerAdapter(ResourceServerEntity entity, EntityManager em, StoreFactory storeFactory) {
|
||||||
|
this.entity = entity;
|
||||||
|
this.em = em;
|
||||||
|
this.storeFactory = storeFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResourceServerEntity getEntity() {
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return entity.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getClientId() {
|
||||||
|
return entity.getClientId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAllowRemoteResourceManagement() {
|
||||||
|
return entity.isAllowRemoteResourceManagement();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAllowRemoteResourceManagement(boolean allowRemoteResourceManagement) {
|
||||||
|
entity.setAllowRemoteResourceManagement(allowRemoteResourceManagement);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PolicyEnforcementMode getPolicyEnforcementMode() {
|
||||||
|
return entity.getPolicyEnforcementMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPolicyEnforcementMode(PolicyEnforcementMode enforcementMode) {
|
||||||
|
entity.setPolicyEnforcementMode(enforcementMode);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || !(o instanceof ResourceServer)) return false;
|
||||||
|
|
||||||
|
ResourceServer that = (ResourceServer) o;
|
||||||
|
return that.getId().equals(getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return getId().hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ResourceServerEntity toEntity(EntityManager em, ResourceServer resource) {
|
||||||
|
if (resource instanceof ResourceAdapter) {
|
||||||
|
return ((ResourceServerAdapter)resource).getEntity();
|
||||||
|
} else {
|
||||||
|
return em.getReference(ResourceServerEntity.class, resource.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,103 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||||
|
* and other contributors as indicated by the @author tags.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.keycloak.authorization.jpa.store;
|
||||||
|
|
||||||
|
import org.keycloak.authorization.AuthorizationProvider;
|
||||||
|
import org.keycloak.authorization.jpa.entities.ScopeEntity;
|
||||||
|
import org.keycloak.authorization.model.ResourceServer;
|
||||||
|
import org.keycloak.authorization.model.Scope;
|
||||||
|
import org.keycloak.authorization.store.StoreFactory;
|
||||||
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
import org.keycloak.models.jpa.JpaModel;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class ScopeAdapter implements Scope, JpaModel<ScopeEntity> {
|
||||||
|
private ScopeEntity entity;
|
||||||
|
private EntityManager em;
|
||||||
|
private StoreFactory storeFactory;
|
||||||
|
|
||||||
|
public ScopeAdapter(ScopeEntity entity, EntityManager em, StoreFactory storeFactory) {
|
||||||
|
this.entity = entity;
|
||||||
|
this.em = em;
|
||||||
|
this.storeFactory = storeFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ScopeEntity getEntity() {
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return entity.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return entity.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setName(String name) {
|
||||||
|
entity.setName(name);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getIconUri() {
|
||||||
|
return entity.getIconUri();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setIconUri(String iconUri) {
|
||||||
|
entity.setIconUri(iconUri);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResourceServer getResourceServer() {
|
||||||
|
return storeFactory.getResourceServerStore().findById(entity.getResourceServer().getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ScopeEntity toEntity(EntityManager em, Scope scope) {
|
||||||
|
if (scope instanceof ScopeAdapter) {
|
||||||
|
return ((ScopeAdapter)scope).getEntity();
|
||||||
|
} else {
|
||||||
|
return em.getReference(ScopeEntity.class, scope.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || !(o instanceof Scope)) return false;
|
||||||
|
|
||||||
|
Scope that = (Scope) o;
|
||||||
|
return that.getId().equals(getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return getId().hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -28,6 +28,7 @@ import org.keycloak.authorization.permission.evaluator.Evaluators;
|
||||||
import org.keycloak.authorization.policy.evaluation.DefaultPolicyEvaluator;
|
import org.keycloak.authorization.policy.evaluation.DefaultPolicyEvaluator;
|
||||||
import org.keycloak.authorization.policy.provider.PolicyProvider;
|
import org.keycloak.authorization.policy.provider.PolicyProvider;
|
||||||
import org.keycloak.authorization.policy.provider.PolicyProviderFactory;
|
import org.keycloak.authorization.policy.provider.PolicyProviderFactory;
|
||||||
|
import org.keycloak.authorization.store.AuthorizationStoreFactory;
|
||||||
import org.keycloak.authorization.store.PolicyStore;
|
import org.keycloak.authorization.store.PolicyStore;
|
||||||
import org.keycloak.authorization.store.ResourceServerStore;
|
import org.keycloak.authorization.store.ResourceServerStore;
|
||||||
import org.keycloak.authorization.store.ResourceStore;
|
import org.keycloak.authorization.store.ResourceStore;
|
||||||
|
@ -35,13 +36,15 @@ import org.keycloak.authorization.store.ScopeStore;
|
||||||
import org.keycloak.authorization.store.StoreFactory;
|
import org.keycloak.authorization.store.StoreFactory;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.RealmModel;
|
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.models.utils.RepresentationToModel;
|
||||||
import org.keycloak.provider.Provider;
|
import org.keycloak.provider.Provider;
|
||||||
import org.keycloak.representations.idm.authorization.AbstractPolicyRepresentation;
|
import org.keycloak.representations.idm.authorization.AbstractPolicyRepresentation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>The main contract here is the creation of {@link org.keycloak.authorization.permission.evaluator.PermissionEvaluator} instances. Usually
|
* <p>The main contract here is the creation of {@link org.keycloak.authorization.permission.evaluator.PermissionEvaluator} instances. Usually
|
||||||
* an application has a single {@link AuthorizationProvider} instance and threads servicing client requests obtain {@link org.keycloak.authorization.core.permission.evaluator.PermissionEvaluator}
|
* an application has a single {@link AuthorizationProvider} instance and threads servicing client requests obtain {@link org.keycloak.authorization.permission.evaluator.PermissionEvaluator}
|
||||||
* from the {@link #evaluators()} method.
|
* from the {@link #evaluators()} method.
|
||||||
*
|
*
|
||||||
* <p>The internal state of a {@link AuthorizationProvider} is immutable. This internal state includes all of the metadata
|
* <p>The internal state of a {@link AuthorizationProvider} is immutable. This internal state includes all of the metadata
|
||||||
|
@ -69,14 +72,14 @@ public final class AuthorizationProvider implements Provider {
|
||||||
|
|
||||||
private final DefaultPolicyEvaluator policyEvaluator;
|
private final DefaultPolicyEvaluator policyEvaluator;
|
||||||
private StoreFactory storeFactory;
|
private StoreFactory storeFactory;
|
||||||
|
private StoreFactory storeFactoryDelegate;
|
||||||
private final Map<String, PolicyProviderFactory> policyProviderFactories;
|
private final Map<String, PolicyProviderFactory> policyProviderFactories;
|
||||||
private final KeycloakSession keycloakSession;
|
private final KeycloakSession keycloakSession;
|
||||||
private final RealmModel realm;
|
private final RealmModel realm;
|
||||||
|
|
||||||
public AuthorizationProvider(KeycloakSession session, RealmModel realm, StoreFactory storeFactory, Map<String, PolicyProviderFactory> policyProviderFactories) {
|
public AuthorizationProvider(KeycloakSession session, RealmModel realm, Map<String, PolicyProviderFactory> policyProviderFactories) {
|
||||||
this.keycloakSession = session;
|
this.keycloakSession = session;
|
||||||
this.realm = realm;
|
this.realm = realm;
|
||||||
this.storeFactory = storeFactory;
|
|
||||||
this.policyProviderFactories = policyProviderFactories;
|
this.policyProviderFactories = policyProviderFactories;
|
||||||
this.policyEvaluator = new DefaultPolicyEvaluator(this);
|
this.policyEvaluator = new DefaultPolicyEvaluator(this);
|
||||||
}
|
}
|
||||||
|
@ -92,15 +95,32 @@ public final class AuthorizationProvider implements Provider {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Cache sits in front of this
|
||||||
|
*
|
||||||
* Returns a {@link StoreFactory}.
|
* Returns a {@link StoreFactory}.
|
||||||
*
|
*
|
||||||
* @return the {@link StoreFactory}
|
* @return the {@link StoreFactory}
|
||||||
*/
|
*/
|
||||||
public StoreFactory getStoreFactory() {
|
public StoreFactory getStoreFactory() {
|
||||||
return createStoreFactory();
|
if (storeFactory != null) return storeFactory;
|
||||||
|
storeFactory = keycloakSession.getProvider(CachedStoreFactoryProvider.class);
|
||||||
|
if (storeFactory == null) storeFactory = getLocalStoreFactory();
|
||||||
|
storeFactory = createStoreFactory(storeFactory);
|
||||||
|
return storeFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
private StoreFactory createStoreFactory() {
|
/**
|
||||||
|
* No cache sits in front of this
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public StoreFactory getLocalStoreFactory() {
|
||||||
|
if (storeFactoryDelegate != null) return storeFactoryDelegate;
|
||||||
|
storeFactoryDelegate = keycloakSession.getProvider(StoreFactory.class);
|
||||||
|
return storeFactoryDelegate;
|
||||||
|
}
|
||||||
|
|
||||||
|
private StoreFactory createStoreFactory(StoreFactory storeFactory) {
|
||||||
return new StoreFactory() {
|
return new StoreFactory() {
|
||||||
@Override
|
@Override
|
||||||
public ResourceStore getResourceStore() {
|
public ResourceStore getResourceStore() {
|
||||||
|
@ -222,7 +242,7 @@ public final class AuthorizationProvider implements Provider {
|
||||||
* Returns a {@link PolicyProviderFactory} given a <code>type</code>.
|
* Returns a {@link PolicyProviderFactory} given a <code>type</code>.
|
||||||
*
|
*
|
||||||
* @param type the type of the policy provider
|
* @param type the type of the policy provider
|
||||||
* @param <F> the expected type of the provider
|
* @param <P> the expected type of the provider
|
||||||
* @return a {@link PolicyProvider} with the given <code>type</code>
|
* @return a {@link PolicyProvider} with the given <code>type</code>
|
||||||
*/
|
*/
|
||||||
public <P extends PolicyProvider> P getProvider(String type) {
|
public <P extends PolicyProvider> P getProvider(String type) {
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||||
|
* and other contributors as indicated by the @author tags.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.keycloak.authorization.model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cached authorization model classes will implement this interface.
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public interface CachedModel<Model> {
|
||||||
|
/**
|
||||||
|
* Invalidates the cache for this model and returns a delegate that represents the actual data provider
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Model getDelegateForUpdate();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invalidate the cache for this model
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void invalidate();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When was the model was loaded from database.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
long getCacheTimestamp();
|
||||||
|
}
|
|
@ -76,10 +76,11 @@ public interface Policy {
|
||||||
/**
|
/**
|
||||||
* Returns a {@link Map} holding string-based key/value pairs representing any additional configuration for this policy.
|
* Returns a {@link Map} holding string-based key/value pairs representing any additional configuration for this policy.
|
||||||
*
|
*
|
||||||
* @return a map with any additional configuration defined for this policy.
|
* @return a unmodifiable map with any additional configuration defined for this policy.
|
||||||
*/
|
*/
|
||||||
Map<String, String> getConfig();
|
Map<String, String> getConfig();
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets a {@link Map} with string-based key/value pairs representing any additional configuration for this policy.
|
* Sets a {@link Map} with string-based key/value pairs representing any additional configuration for this policy.
|
||||||
*
|
*
|
||||||
|
@ -87,6 +88,9 @@ public interface Policy {
|
||||||
*/
|
*/
|
||||||
void setConfig(Map<String, String> config);
|
void setConfig(Map<String, String> config);
|
||||||
|
|
||||||
|
void removeConfig(String name);
|
||||||
|
void putConfig(String name, String value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the name of this policy.
|
* Returns the name of this policy.
|
||||||
*
|
*
|
||||||
|
@ -120,7 +124,7 @@ public interface Policy {
|
||||||
*
|
*
|
||||||
* @return a resource server
|
* @return a resource server
|
||||||
*/
|
*/
|
||||||
<R extends ResourceServer> R getResourceServer();
|
ResourceServer getResourceServer();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the {@link Policy} instances associated with this policy and used to evaluate authorization decisions when
|
* Returns the {@link Policy} instances associated with this policy and used to evaluate authorization decisions when
|
||||||
|
@ -128,21 +132,21 @@ public interface Policy {
|
||||||
*
|
*
|
||||||
* @return the associated policies or an empty set if no policy is associated with this policy
|
* @return the associated policies or an empty set if no policy is associated with this policy
|
||||||
*/
|
*/
|
||||||
<P extends Policy> Set<P> getAssociatedPolicies();
|
Set<Policy> getAssociatedPolicies();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the {@link Resource} instances where this policy applies.
|
* Returns the {@link Resource} instances where this policy applies.
|
||||||
*
|
*
|
||||||
* @return a set with all resource instances where this policy applies. Or an empty set if there is no resource associated with this policy
|
* @return a set with all resource instances where this policy applies. Or an empty set if there is no resource associated with this policy
|
||||||
*/
|
*/
|
||||||
<R extends Resource> Set<R> getResources();
|
Set<Resource> getResources();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the {@link Scope} instances where this policy applies.
|
* Returns the {@link Scope} instances where this policy applies.
|
||||||
*
|
*
|
||||||
* @return a set with all scope instances where this policy applies. Or an empty set if there is no scope associated with this policy
|
* @return a set with all scope instances where this policy applies. Or an empty set if there is no scope associated with this policy
|
||||||
*/
|
*/
|
||||||
<S extends Scope> Set<S> getScopes();
|
Set<Scope> getScopes();
|
||||||
|
|
||||||
void addScope(Scope scope);
|
void addScope(Scope scope);
|
||||||
|
|
||||||
|
|
|
@ -82,7 +82,7 @@ public interface Resource {
|
||||||
*
|
*
|
||||||
* @return a list with all scopes associated with this resource
|
* @return a list with all scopes associated with this resource
|
||||||
*/
|
*/
|
||||||
<S extends Scope> List<S> getScopes();
|
List<Scope> getScopes();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an icon {@link java.net.URI} for this resource.
|
* Returns an icon {@link java.net.URI} for this resource.
|
||||||
|
@ -103,7 +103,7 @@ public interface Resource {
|
||||||
*
|
*
|
||||||
* @return the resource server associated with this resource
|
* @return the resource server associated with this resource
|
||||||
*/
|
*/
|
||||||
<R extends ResourceServer> R getResourceServer();
|
ResourceServer getResourceServer();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the resource's owner, which is usually an identifier that uniquely identifies the resource's owner.
|
* Returns the resource's owner, which is usually an identifier that uniquely identifies the resource's owner.
|
||||||
|
|
|
@ -21,10 +21,12 @@ package org.keycloak.authorization.store;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.keycloak.authorization.AuthorizationProvider;
|
||||||
import org.keycloak.authorization.store.syncronization.ClientApplicationSynchronizer;
|
import org.keycloak.authorization.store.syncronization.ClientApplicationSynchronizer;
|
||||||
import org.keycloak.authorization.store.syncronization.RealmSynchronizer;
|
import org.keycloak.authorization.store.syncronization.RealmSynchronizer;
|
||||||
import org.keycloak.authorization.store.syncronization.Synchronizer;
|
import org.keycloak.authorization.store.syncronization.Synchronizer;
|
||||||
import org.keycloak.authorization.store.syncronization.UserSynchronizer;
|
import org.keycloak.authorization.store.syncronization.UserSynchronizer;
|
||||||
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.KeycloakSessionFactory;
|
import org.keycloak.models.KeycloakSessionFactory;
|
||||||
import org.keycloak.models.RealmModel.ClientRemovedEvent;
|
import org.keycloak.models.RealmModel.ClientRemovedEvent;
|
||||||
import org.keycloak.models.RealmModel.RealmRemovedEvent;
|
import org.keycloak.models.RealmModel.RealmRemovedEvent;
|
||||||
|
|
|
@ -66,7 +66,7 @@ public interface ResourceStore {
|
||||||
/**
|
/**
|
||||||
* Finds all {@link Resource} instances with the given uri.
|
* Finds all {@link Resource} instances with the given uri.
|
||||||
*
|
*
|
||||||
* @param ownerId the identifier of the owner
|
* @param uri the identifier of the uri
|
||||||
* @return a list with all resource instances owned by the given owner
|
* @return a list with all resource instances owned by the given owner
|
||||||
*/
|
*/
|
||||||
List<Resource> findByUri(String uri, String resourceServerId);
|
List<Resource> findByUri(String uri, String resourceServerId);
|
||||||
|
|
|
@ -41,9 +41,9 @@ public class ClientApplicationSynchronizer implements Synchronizer<ClientRemoved
|
||||||
|
|
||||||
if (resourceServer != null) {
|
if (resourceServer != null) {
|
||||||
String id = resourceServer.getId();
|
String id = resourceServer.getId();
|
||||||
storeFactory.getResourceStore().findByResourceServer(id).forEach(resource -> storeFactory.getResourceStore().delete(resource.getId()));
|
//storeFactory.getResourceStore().findByResourceServer(id).forEach(resource -> storeFactory.getResourceStore().delete(resource.getId()));
|
||||||
storeFactory.getScopeStore().findByResourceServer(id).forEach(scope -> storeFactory.getScopeStore().delete(scope.getId()));
|
//storeFactory.getScopeStore().findByResourceServer(id).forEach(scope -> storeFactory.getScopeStore().delete(scope.getId()));
|
||||||
storeFactory.getPolicyStore().findByResourceServer(id).forEach(scope -> storeFactory.getPolicyStore().delete(scope.getId()));
|
//storeFactory.getPolicyStore().findByResourceServer(id).forEach(scope -> storeFactory.getPolicyStore().delete(scope.getId()));
|
||||||
storeFactory.getResourceServerStore().delete(id);
|
storeFactory.getResourceServerStore().delete(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,7 +71,7 @@ public class MigrateTo2_1_0 implements Migration {
|
||||||
|
|
||||||
if (resourceServer != null) {
|
if (resourceServer != null) {
|
||||||
policyStore.findByType("role", resourceServer.getId()).forEach(policy -> {
|
policyStore.findByType("role", resourceServer.getId()).forEach(policy -> {
|
||||||
Map<String, String> config = policy.getConfig();
|
Map<String, String> config = new HashMap(policy.getConfig());
|
||||||
String roles = config.get("roles");
|
String roles = config.get("roles");
|
||||||
List roleConfig;
|
List roleConfig;
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,9 @@
|
||||||
|
|
||||||
package org.keycloak.models.cache.authorization;
|
package org.keycloak.models.cache.authorization;
|
||||||
|
|
||||||
|
import org.keycloak.authorization.AuthorizationProvider;
|
||||||
|
import org.keycloak.authorization.store.StoreFactory;
|
||||||
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.provider.ProviderFactory;
|
import org.keycloak.provider.ProviderFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -2110,7 +2110,7 @@ public class RepresentationToModel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
policy.getConfig().remove("scopes");
|
policy.removeConfig("scopes");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void updateAssociatedPolicies(Set<String> policyIds, Policy policy, StoreFactory storeFactory) {
|
private static void updateAssociatedPolicies(Set<String> policyIds, Policy policy, StoreFactory storeFactory) {
|
||||||
|
@ -2163,7 +2163,7 @@ public class RepresentationToModel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
policy.getConfig().remove("applyPolicies");
|
policy.removeConfig("applyPolicies");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void updateResources(Set<String> resourceIds, Policy policy, StoreFactory storeFactory) {
|
private static void updateResources(Set<String> resourceIds, Policy policy, StoreFactory storeFactory) {
|
||||||
|
@ -2209,7 +2209,7 @@ public class RepresentationToModel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
policy.getConfig().remove("resources");
|
policy.removeConfig("resources");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Resource toModel(ResourceRepresentation resource, ResourceServer resourceServer, AuthorizationProvider authorization) {
|
public static Resource toModel(ResourceRepresentation resource, ResourceServer resourceServer, AuthorizationProvider authorization) {
|
||||||
|
|
|
@ -65,11 +65,7 @@ public class DefaultAuthorizationProviderFactory implements AuthorizationProvide
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AuthorizationProvider create(KeycloakSession session, RealmModel realm) {
|
public AuthorizationProvider create(KeycloakSession session, RealmModel realm) {
|
||||||
StoreFactory storeFactory = session.getProvider(CachedStoreFactoryProvider.class);
|
return new AuthorizationProvider(session, realm, policyProviderFactories);
|
||||||
if (storeFactory == null) {
|
|
||||||
storeFactory = session.getProvider(StoreFactory.class);
|
|
||||||
}
|
|
||||||
return new AuthorizationProvider(session, realm, storeFactory, policyProviderFactories);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, PolicyProviderFactory> configurePolicyProviderFactories(KeycloakSessionFactory keycloakSessionFactory) {
|
private Map<String, PolicyProviderFactory> configurePolicyProviderFactories(KeycloakSessionFactory keycloakSessionFactory) {
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.authorization.authorization;
|
package org.keycloak.authorization.authorization;
|
||||||
|
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.jboss.resteasy.spi.HttpRequest;
|
||||||
import org.keycloak.OAuth2Constants;
|
import org.keycloak.OAuth2Constants;
|
||||||
import org.keycloak.OAuthErrorException;
|
import org.keycloak.OAuthErrorException;
|
||||||
|
@ -46,6 +47,7 @@ import org.keycloak.representations.idm.authorization.Permission;
|
||||||
import org.keycloak.representations.idm.authorization.ScopeRepresentation;
|
import org.keycloak.representations.idm.authorization.ScopeRepresentation;
|
||||||
import org.keycloak.services.ErrorResponseException;
|
import org.keycloak.services.ErrorResponseException;
|
||||||
import org.keycloak.services.resources.Cors;
|
import org.keycloak.services.resources.Cors;
|
||||||
|
import org.keycloak.services.resources.RealmsResource;
|
||||||
|
|
||||||
import javax.ws.rs.Consumes;
|
import javax.ws.rs.Consumes;
|
||||||
import javax.ws.rs.OPTIONS;
|
import javax.ws.rs.OPTIONS;
|
||||||
|
@ -72,6 +74,7 @@ import java.util.stream.Stream;
|
||||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||||
*/
|
*/
|
||||||
public class AuthorizationTokenService {
|
public class AuthorizationTokenService {
|
||||||
|
protected static final Logger logger = Logger.getLogger(AuthorizationTokenService.class);
|
||||||
|
|
||||||
private final AuthorizationProvider authorization;
|
private final AuthorizationProvider authorization;
|
||||||
|
|
||||||
|
@ -131,6 +134,7 @@ public class AuthorizationTokenService {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onError(Throwable cause) {
|
public void onError(Throwable cause) {
|
||||||
|
logger.error("failed authorize", cause);
|
||||||
asyncResponse.resume(cause);
|
asyncResponse.resume(cause);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -41,10 +41,12 @@ import javax.ws.rs.core.Context;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
import javax.ws.rs.core.Response.Status;
|
import javax.ws.rs.core.Response.Status;
|
||||||
|
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.jboss.resteasy.spi.HttpRequest;
|
||||||
import org.keycloak.OAuth2Constants;
|
import org.keycloak.OAuth2Constants;
|
||||||
import org.keycloak.OAuthErrorException;
|
import org.keycloak.OAuthErrorException;
|
||||||
import org.keycloak.authorization.AuthorizationProvider;
|
import org.keycloak.authorization.AuthorizationProvider;
|
||||||
|
import org.keycloak.authorization.authorization.AuthorizationTokenService;
|
||||||
import org.keycloak.authorization.common.KeycloakEvaluationContext;
|
import org.keycloak.authorization.common.KeycloakEvaluationContext;
|
||||||
import org.keycloak.authorization.common.KeycloakIdentity;
|
import org.keycloak.authorization.common.KeycloakIdentity;
|
||||||
import org.keycloak.authorization.entitlement.representation.EntitlementRequest;
|
import org.keycloak.authorization.entitlement.representation.EntitlementRequest;
|
||||||
|
@ -79,6 +81,7 @@ import org.keycloak.services.resources.Cors;
|
||||||
*/
|
*/
|
||||||
public class EntitlementService {
|
public class EntitlementService {
|
||||||
|
|
||||||
|
protected static final Logger logger = Logger.getLogger(EntitlementService.class);
|
||||||
private final AuthorizationProvider authorization;
|
private final AuthorizationProvider authorization;
|
||||||
|
|
||||||
@Context
|
@Context
|
||||||
|
@ -122,6 +125,7 @@ public class EntitlementService {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onError(Throwable cause) {
|
public void onError(Throwable cause) {
|
||||||
|
logger.error("failed", cause);
|
||||||
asyncResponse.resume(cause);
|
asyncResponse.resume(cause);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,6 +179,7 @@ public class EntitlementService {
|
||||||
authorization.evaluators().from(createPermissions(entitlementRequest, resourceServer, authorization), new KeycloakEvaluationContext(this.authorization.getKeycloakSession())).evaluate(new DecisionResultCollector() {
|
authorization.evaluators().from(createPermissions(entitlementRequest, resourceServer, authorization), new KeycloakEvaluationContext(this.authorization.getKeycloakSession())).evaluate(new DecisionResultCollector() {
|
||||||
@Override
|
@Override
|
||||||
public void onError(Throwable cause) {
|
public void onError(Throwable cause) {
|
||||||
|
logger.error("failed", cause);
|
||||||
asyncResponse.resume(cause);
|
asyncResponse.resume(cause);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ package org.keycloak.authorization.util;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
@ -61,8 +62,8 @@ public final class Permissions {
|
||||||
StoreFactory storeFactory = authorization.getStoreFactory();
|
StoreFactory storeFactory = authorization.getStoreFactory();
|
||||||
ResourceStore resourceStore = storeFactory.getResourceStore();
|
ResourceStore resourceStore = storeFactory.getResourceStore();
|
||||||
|
|
||||||
resourceStore.findByOwner(resourceServer.getClientId(), resourceServer.getId()).stream().forEach(resource -> permissions.addAll(createResourcePermissionsWithScopes(resource, resource.getScopes(), authorization)));
|
resourceStore.findByOwner(resourceServer.getClientId(), resourceServer.getId()).stream().forEach(resource -> permissions.addAll(createResourcePermissionsWithScopes(resource, new LinkedList(resource.getScopes()), authorization)));
|
||||||
resourceStore.findByOwner(identity.getId(), resourceServer.getId()).stream().forEach(resource -> permissions.addAll(createResourcePermissionsWithScopes(resource, resource.getScopes(), authorization)));
|
resourceStore.findByOwner(identity.getId(), resourceServer.getId()).stream().forEach(resource -> permissions.addAll(createResourcePermissionsWithScopes(resource, new LinkedList(resource.getScopes()), authorization)));
|
||||||
|
|
||||||
return permissions;
|
return permissions;
|
||||||
}
|
}
|
||||||
|
@ -74,7 +75,7 @@ public final class Permissions {
|
||||||
List<Scope> scopes;
|
List<Scope> scopes;
|
||||||
|
|
||||||
if (requestedScopes.isEmpty()) {
|
if (requestedScopes.isEmpty()) {
|
||||||
scopes = resource.getScopes();
|
scopes = new LinkedList<>(resource.getScopes());
|
||||||
// check if there is a typed resource whose scopes are inherited by the resource being requested. In this case, we assume that parent resource
|
// check if there is a typed resource whose scopes are inherited by the resource being requested. In this case, we assume that parent resource
|
||||||
// is owned by the resource server itself
|
// is owned by the resource server itself
|
||||||
if (type != null && !resource.getOwner().equals(resourceServer.getClientId())) {
|
if (type != null && !resource.getOwner().equals(resourceServer.getClientId())) {
|
||||||
|
@ -102,7 +103,6 @@ public final class Permissions {
|
||||||
return byName;
|
return byName;
|
||||||
}).collect(Collectors.toList());
|
}).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
permissions.add(new ResourcePermission(resource, scopes, resource.getResourceServer()));
|
permissions.add(new ResourcePermission(resource, scopes, resource.getResourceServer()));
|
||||||
|
|
||||||
return permissions;
|
return permissions;
|
||||||
|
|
|
@ -213,7 +213,7 @@ public class ConflictingScopePermissionTest extends AbstractKeycloakTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
representation.addScope(scopes.toArray(new String[scopes.size()]));
|
representation.addScope(scopes.toArray(new String[scopes.size()]));
|
||||||
representation.addPolicy(scopes.toArray(new String[policies.size()]));
|
representation.addPolicy(policies.toArray(new String[policies.size()]));
|
||||||
|
|
||||||
authorization.permissions().scope().create(representation);
|
authorization.permissions().scope().create(representation);
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
<local-cache name="loginFailures"/>
|
<local-cache name="loginFailures"/>
|
||||||
<local-cache name="work"/>
|
<local-cache name="work"/>
|
||||||
<local-cache name="authorization">
|
<local-cache name="authorization">
|
||||||
<eviction max-entries="100" strategy="LRU"/>
|
<eviction max-entries="10000" strategy="LRU"/>
|
||||||
</local-cache>
|
</local-cache>
|
||||||
<local-cache name="keys">
|
<local-cache name="keys">
|
||||||
<eviction max-entries="1000" strategy="LRU"/>
|
<eviction max-entries="1000" strategy="LRU"/>
|
||||||
|
|
Loading…
Reference in a new issue