diff --git a/common/src/main/java/org/keycloak/common/Profile.java b/common/src/main/java/org/keycloak/common/Profile.java index 73d65745c6..7d87f6ea85 100755 --- a/common/src/main/java/org/keycloak/common/Profile.java +++ b/common/src/main/java/org/keycloak/common/Profile.java @@ -103,6 +103,7 @@ public class Profile { TRANSIENT_USERS("Transient users for brokering", Type.EXPERIMENTAL), MULTI_SITE("Multi-site support", Type.DISABLED_BY_DEFAULT), + REMOTE_CACHE("Remote caches support. Requires Multi-site support to be enabled as well.", Type.EXPERIMENTAL), CLIENT_TYPES("Client Types", Type.EXPERIMENTAL), diff --git a/common/src/main/java/org/keycloak/common/util/MultiSiteUtils.java b/common/src/main/java/org/keycloak/common/util/MultiSiteUtils.java new file mode 100644 index 0000000000..eca522b707 --- /dev/null +++ b/common/src/main/java/org/keycloak/common/util/MultiSiteUtils.java @@ -0,0 +1,34 @@ +/* + * Copyright 2024 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.common.util; + +import org.keycloak.common.Profile; + +public class MultiSiteUtils { + + public static boolean isMultiSiteEnabled() { + return Profile.isFeatureEnabled(Profile.Feature.MULTI_SITE); + } + + /** + * @return true when user sessions are stored in the database. In multi-site setup this is false when REMOTE_CACHE feature is enabled + */ + public static boolean isPersistentSessionsEnabled() { + return Profile.isFeatureEnabled(Profile.Feature.PERSISTENT_USER_SESSIONS) || (isMultiSiteEnabled() && !Profile.isFeatureEnabled(Profile.Feature.REMOTE_CACHE)); + } +} diff --git a/model/infinispan/src/main/java/org/keycloak/connections/infinispan/remote/RemoteLoadBalancerCheckProviderFactory.java b/model/infinispan/src/main/java/org/keycloak/connections/infinispan/remote/RemoteLoadBalancerCheckProviderFactory.java index aed35900f9..de02dc9b31 100644 --- a/model/infinispan/src/main/java/org/keycloak/connections/infinispan/remote/RemoteLoadBalancerCheckProviderFactory.java +++ b/model/infinispan/src/main/java/org/keycloak/connections/infinispan/remote/RemoteLoadBalancerCheckProviderFactory.java @@ -25,6 +25,7 @@ import org.infinispan.persistence.manager.PersistenceManager; import org.infinispan.util.concurrent.ActionSequencer; import org.jboss.logging.Logger; import org.keycloak.Config; +import org.keycloak.common.util.MultiSiteUtils; import org.keycloak.connections.infinispan.InfinispanConnectionProvider; import org.keycloak.health.LoadBalancerCheckProvider; import org.keycloak.health.LoadBalancerCheckProviderFactory; @@ -62,7 +63,7 @@ public class RemoteLoadBalancerCheckProviderFactory implements LoadBalancerCheck @Override public boolean isSupported(Config.Scope config) { - return InfinispanUtils.isRemoteInfinispan(); + return MultiSiteUtils.isMultiSiteEnabled(); } @Override diff --git a/model/infinispan/src/main/java/org/keycloak/infinispan/util/InfinispanUtils.java b/model/infinispan/src/main/java/org/keycloak/infinispan/util/InfinispanUtils.java index 0ef9cc6644..ecfe9569d7 100644 --- a/model/infinispan/src/main/java/org/keycloak/infinispan/util/InfinispanUtils.java +++ b/model/infinispan/src/main/java/org/keycloak/infinispan/util/InfinispanUtils.java @@ -18,9 +18,8 @@ package org.keycloak.infinispan.util; import org.keycloak.common.Profile; -import org.keycloak.common.Profile.Feature; +import org.keycloak.common.util.MultiSiteUtils; -import static org.keycloak.common.Profile.Feature.MULTI_SITE; import static org.keycloak.common.Profile.Feature.REMOTE_CACHE; public final class InfinispanUtils { @@ -39,11 +38,11 @@ public final class InfinispanUtils { // true if running with external infinispan mode only public static boolean isRemoteInfinispan() { - return Profile.isFeatureEnabled(Feature.MULTI_SITE) && Profile.isFeatureEnabled(REMOTE_CACHE); + return MultiSiteUtils.isMultiSiteEnabled() || Profile.isFeatureEnabled(REMOTE_CACHE); } // true if running with embedded caches. public static boolean isEmbeddedInfinispan() { - return !Profile.isFeatureEnabled(MULTI_SITE) || !Profile.isFeatureEnabled(REMOTE_CACHE); + return !isRemoteInfinispan(); } } diff --git a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/InfinispanUserSessionProviderFactory.java b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/InfinispanUserSessionProviderFactory.java index 219506994b..2bf564e462 100755 --- a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/InfinispanUserSessionProviderFactory.java +++ b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/InfinispanUserSessionProviderFactory.java @@ -32,8 +32,8 @@ import org.infinispan.persistence.remote.RemoteStore; import org.jboss.logging.Logger; import org.keycloak.Config; import org.keycloak.cluster.ClusterProvider; -import org.keycloak.common.Profile; import org.keycloak.common.util.Environment; +import org.keycloak.common.util.MultiSiteUtils; import org.keycloak.common.util.Time; import org.keycloak.connections.infinispan.InfinispanConnectionProvider; import org.keycloak.connections.infinispan.InfinispanUtil; @@ -77,8 +77,6 @@ import org.keycloak.provider.ProviderEvent; import org.keycloak.provider.ProviderEventListener; import org.keycloak.provider.ServerInfoAwareProviderFactory; -import static org.keycloak.common.Profile.Feature.PERSISTENT_USER_SESSIONS; - public class InfinispanUserSessionProviderFactory implements UserSessionProviderFactory, ServerInfoAwareProviderFactory, EnvironmentDependentProviderFactory { private static final Logger log = Logger.getLogger(InfinispanUserSessionProviderFactory.class); @@ -131,7 +129,7 @@ public class InfinispanUserSessionProviderFactory implements UserSessionProvider offlineClientSessionsCache = connections.getCache(InfinispanConnectionProvider.OFFLINE_CLIENT_SESSION_CACHE_NAME); } - if (Profile.isFeatureEnabled(Profile.Feature.PERSISTENT_USER_SESSIONS)) { + if (MultiSiteUtils.isPersistentSessionsEnabled()) { return new PersistentUserSessionProvider( session, remoteCacheInvoker, @@ -175,8 +173,9 @@ public class InfinispanUserSessionProviderFactory implements UserSessionProvider offlineSessionCacheEntryLifespanOverride = config.getInt(CONFIG_OFFLINE_SESSION_CACHE_ENTRY_LIFESPAN_OVERRIDE, -1); offlineClientSessionCacheEntryLifespanOverride = config.getInt(CONFIG_OFFLINE_CLIENT_SESSION_CACHE_ENTRY_LIFESPAN_OVERRIDE, -1); maxBatchSize = config.getInt(CONFIG_MAX_BATCH_SIZE, DEFAULT_MAX_BATCH_SIZE); + // Do not use caches for sessions if explicitly disabled or if embedded caches are not used useCaches = config.getBoolean(CONFIG_USE_CACHES, DEFAULT_USE_CACHES) && InfinispanUtils.isEmbeddedInfinispan(); - useBatches = config.getBoolean(CONFIG_USE_BATCHES, DEFAULT_USE_BATCHES) && Profile.isFeatureEnabled(PERSISTENT_USER_SESSIONS); + useBatches = config.getBoolean(CONFIG_USE_BATCHES, DEFAULT_USE_BATCHES) && MultiSiteUtils.isPersistentSessionsEnabled(); if (useBatches) { asyncQueuePersistentUpdate = new ArrayBlockingQueue<>(1000); } @@ -204,7 +203,7 @@ public class InfinispanUserSessionProviderFactory implements UserSessionProvider keyGenerator = new InfinispanKeyGenerator(); checkRemoteCaches(session); - if (!Profile.isFeatureEnabled(Profile.Feature.PERSISTENT_USER_SESSIONS)) { + if (!MultiSiteUtils.isPersistentSessionsEnabled()) { initializeLastSessionRefreshStore(factory); } registerClusterListeners(session); @@ -237,7 +236,7 @@ public class InfinispanUserSessionProviderFactory implements UserSessionProvider } } }); - if (Profile.isFeatureEnabled(Profile.Feature.PERSISTENT_USER_SESSIONS) && useBatches) { + if (MultiSiteUtils.isPersistentSessionsEnabled() && useBatches) { persistentSessionsWorker = new PersistentSessionsWorker(factory, asyncQueuePersistentUpdate, maxBatchSize); @@ -367,7 +366,7 @@ public class InfinispanUserSessionProviderFactory implements UserSessionProvider remoteCacheInvoker.addRemoteCache(ispnCache.getName(), remoteCache, maxIdleLoader); Runnable onFailover = null; - if (useCaches && Profile.isFeatureEnabled(Profile.Feature.PERSISTENT_USER_SESSIONS)) { + if (useCaches && MultiSiteUtils.isPersistentSessionsEnabled()) { // If persistent sessions are enabled, we want to clear the local caches when a failover of the listener on the remote store changes as we might have missed some of the remote store events // which might have been triggered by another Keycloak site connected to the same remote Infinispan cluster. // Due to this, we can be sure that we never have outdated information in our local cache. All entries will be re-loaded from the remote cache or the database as necessary lazily. @@ -465,7 +464,7 @@ public class InfinispanUserSessionProviderFactory implements UserSessionProvider @Override public boolean isSupported(Config.Scope config) { - return InfinispanUtils.isEmbeddedInfinispan() || Profile.isFeatureEnabled(PERSISTENT_USER_SESSIONS); + return InfinispanUtils.isEmbeddedInfinispan() || MultiSiteUtils.isPersistentSessionsEnabled(); } @Override diff --git a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/PersistentUserSessionProvider.java b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/PersistentUserSessionProvider.java index f56e6612b8..b4f7301093 100755 --- a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/PersistentUserSessionProvider.java +++ b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/PersistentUserSessionProvider.java @@ -48,6 +48,7 @@ import org.jboss.logging.Logger; import org.keycloak.cluster.ClusterProvider; import org.keycloak.common.Profile; import org.keycloak.common.Profile.Feature; +import org.keycloak.common.util.MultiSiteUtils; import org.keycloak.common.util.Retry; import org.keycloak.common.util.Time; import org.keycloak.connections.infinispan.InfinispanConnectionProvider; @@ -134,7 +135,7 @@ public class PersistentUserSessionProvider implements UserSessionProvider, Sessi SerializeExecutionsByKey serializerOfflineSession, SerializeExecutionsByKey serializerClientSession, SerializeExecutionsByKey serializerOfflineClientSession) { - if (!Profile.isFeatureEnabled(Profile.Feature.PERSISTENT_USER_SESSIONS)) { + if (!MultiSiteUtils.isPersistentSessionsEnabled()) { throw new IllegalStateException("Persistent user sessions are not enabled"); } diff --git a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/UserSessionAdapter.java b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/UserSessionAdapter.java index 3a9e8083f6..9b6635366f 100755 --- a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/UserSessionAdapter.java +++ b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/UserSessionAdapter.java @@ -17,7 +17,7 @@ package org.keycloak.models.sessions.infinispan; -import org.keycloak.common.Profile; +import org.keycloak.common.util.MultiSiteUtils; import org.keycloak.models.AuthenticatedClientSessionModel; import org.keycloak.models.ClientModel; import org.keycloak.models.KeycloakSession; @@ -231,7 +231,7 @@ public class UserSessionAdapter> versioned = remoteCache.getWithMetadata(key); if (versioned == null) { - if (Profile.isFeatureEnabled(Profile.Feature.PERSISTENT_USER_SESSIONS) && + if (MultiSiteUtils.isPersistentSessionsEnabled() && (remoteCache.getName().equals(USER_SESSION_CACHE_NAME) || remoteCache.getName().equals(CLIENT_SESSION_CACHE_NAME) || remoteCache.getName().equals(OFFLINE_USER_SESSION_CACHE_NAME) diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/session/JpaUserSessionPersisterProvider.java b/model/jpa/src/main/java/org/keycloak/models/jpa/session/JpaUserSessionPersisterProvider.java index aa1f828628..3e253302dd 100644 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/session/JpaUserSessionPersisterProvider.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/session/JpaUserSessionPersisterProvider.java @@ -18,7 +18,7 @@ package org.keycloak.models.jpa.session; import org.jboss.logging.Logger; -import org.keycloak.common.Profile; +import org.keycloak.common.util.MultiSiteUtils; import org.keycloak.common.util.Time; import org.keycloak.models.AuthenticatedClientSessionModel; import org.keycloak.models.ClientModel; @@ -253,7 +253,7 @@ public class JpaUserSessionPersisterProvider implements UserSessionPersisterProv expire(realm, expiredClientOffline, expiredOffline, true); - if (Profile.isFeatureEnabled(Profile.Feature.PERSISTENT_USER_SESSIONS)) { + if (MultiSiteUtils.isPersistentSessionsEnabled()) { int expired = Time.currentTime() - Math.max(realm.getSsoSessionIdleTimeout(), realm.getSsoSessionIdleTimeoutRememberMe()) - SessionTimeoutHelper.PERIODIC_CLEANER_IDLE_TIMEOUT_WINDOW_SECONDS; diff --git a/model/storage-private/src/main/java/org/keycloak/models/session/PersistentUserSessionAdapter.java b/model/storage-private/src/main/java/org/keycloak/models/session/PersistentUserSessionAdapter.java index a6ceeca9de..4bfd326fdb 100644 --- a/model/storage-private/src/main/java/org/keycloak/models/session/PersistentUserSessionAdapter.java +++ b/model/storage-private/src/main/java/org/keycloak/models/session/PersistentUserSessionAdapter.java @@ -18,7 +18,7 @@ package org.keycloak.models.session; import com.fasterxml.jackson.annotation.JsonProperty; -import org.keycloak.common.Profile; +import org.keycloak.common.util.MultiSiteUtils; import org.keycloak.models.AuthenticatedClientSessionModel; import org.keycloak.models.KeycloakSession; import org.keycloak.models.ModelException; @@ -216,7 +216,7 @@ public class PersistentUserSessionAdapter implements OfflineUserSessionModel { @Override public String getLoginUsername() { - if (isOffline() || !Profile.isFeatureEnabled(Profile.Feature.PERSISTENT_USER_SESSIONS)) { + if (isOffline() || !MultiSiteUtils.isPersistentSessionsEnabled()) { return getUser().getUsername(); } else { return getData().getLoginUsername(); diff --git a/quarkus/deployment/src/main/java/org/keycloak/quarkus/deployment/KeycloakProcessor.java b/quarkus/deployment/src/main/java/org/keycloak/quarkus/deployment/KeycloakProcessor.java index e3e110e018..b24d7cdddd 100644 --- a/quarkus/deployment/src/main/java/org/keycloak/quarkus/deployment/KeycloakProcessor.java +++ b/quarkus/deployment/src/main/java/org/keycloak/quarkus/deployment/KeycloakProcessor.java @@ -68,6 +68,7 @@ import org.keycloak.authorization.policy.provider.PolicySpi; import org.keycloak.authorization.policy.provider.js.DeployedScriptPolicyFactory; import org.keycloak.common.Profile; import org.keycloak.common.crypto.FipsMode; +import org.keycloak.common.util.MultiSiteUtils; import org.keycloak.common.util.StreamUtil; import org.keycloak.config.DatabaseOptions; import org.keycloak.config.HealthOptions; @@ -644,7 +645,7 @@ class KeycloakProcessor { JsResource.class.getName())), false)); } - if (!Profile.isFeatureEnabled(Profile.Feature.MULTI_SITE)) { + if (!MultiSiteUtils.isMultiSiteEnabled()) { buildTimeConditionBuildItemBuildProducer.produce(new BuildTimeConditionBuildItem(index.getIndex().getClassByName(DotName.createSimple( LoadBalancerResource.class.getName())), false)); } diff --git a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/storage/legacy/infinispan/CacheManagerFactory.java b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/storage/legacy/infinispan/CacheManagerFactory.java index f4a049c7cc..fc0910e55c 100644 --- a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/storage/legacy/infinispan/CacheManagerFactory.java +++ b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/storage/legacy/infinispan/CacheManagerFactory.java @@ -58,6 +58,7 @@ import org.jgroups.protocols.UDP; import org.jgroups.util.TLS; import org.jgroups.util.TLSClientAuth; import org.keycloak.common.Profile; +import org.keycloak.common.util.MultiSiteUtils; import org.keycloak.config.CachingOptions; import org.keycloak.config.MetricsOptions; import org.keycloak.infinispan.util.InfinispanUtils; @@ -297,7 +298,7 @@ public class CacheManagerFactory { Arrays.stream(CLUSTERED_CACHE_NAMES).forEach(cacheName -> { if (cacheName.equals(USER_SESSION_CACHE_NAME) || cacheName.equals(CLIENT_SESSION_CACHE_NAME) || cacheName.equals(OFFLINE_USER_SESSION_CACHE_NAME) || cacheName.equals(OFFLINE_CLIENT_SESSION_CACHE_NAME)) { ConfigurationBuilder configurationBuilder = builder.getNamedConfigurationBuilders().get(cacheName); - if (Profile.isFeatureEnabled(Profile.Feature.PERSISTENT_USER_SESSIONS)) { + if (MultiSiteUtils.isPersistentSessionsEnabled()) { if (configurationBuilder.memory().maxCount() == -1) { logger.infof("Persistent user sessions enabled and no memory limit found in configuration. Setting max entries for %s to 10000 entries.", cacheName); configurationBuilder.memory().maxCount(10000); diff --git a/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/HealthDistTest.java b/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/HealthDistTest.java index 1ae011690e..0661222b67 100644 --- a/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/HealthDistTest.java +++ b/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/HealthDistTest.java @@ -122,13 +122,4 @@ public class HealthDistTest { distribution.stop(); } } - - @Test - @Launch({ "start-dev", "--features=multi-site" }) - void testLoadBalancerCheck(KeycloakDistribution distribution) { - distribution.setRequestPort(8080); - - when().get("/lb-check").then() - .statusCode(200); - } } diff --git a/quarkus/tests/integration/src/test/java/org/keycloak/it/storage/database/ExternalInfinispanTest.java b/quarkus/tests/integration/src/test/java/org/keycloak/it/storage/database/ExternalInfinispanTest.java index d36b24762f..abf10e950d 100644 --- a/quarkus/tests/integration/src/test/java/org/keycloak/it/storage/database/ExternalInfinispanTest.java +++ b/quarkus/tests/integration/src/test/java/org/keycloak/it/storage/database/ExternalInfinispanTest.java @@ -34,8 +34,20 @@ import static io.restassured.RestAssured.when; public class ExternalInfinispanTest { @Test - @Launch({ "start-dev", "--features=multi-site", "--cache=ispn", "--cache-config-file=../../../test-classes/ExternalInfinispan/kcb-infinispan-cache-remote-store-config.xml", "--spi-connections-infinispan-quarkus-site-name=ISPN" }) - void testLoadBalancerCheckFailure() { + @Launch({ + "start-dev", + "--features=multi-site", + "--cache=ispn", + "--cache-remote-host=localhost", + "--cache-remote-username=keycloak", + "--cache-remote-password=Password1!", + "--cache-remote-tls-enabled=false", + "--spi-connections-infinispan-quarkus-site-name=ISPN", + "--spi-load-balancer-check-remote-poll-interval=500", + "-Dkc.cache-remote-create-caches=true", + "--verbose" + }) + void testLoadBalancerCheckFailureWithMultiSite() { runLoadBalancerCheckFailureTest(); } @@ -47,9 +59,10 @@ public class ExternalInfinispanTest { "--cache-remote-host=localhost", "--cache-remote-username=keycloak", "--cache-remote-password=Password1!", + "--cache-remote-tls-enabled=false", "--spi-connections-infinispan-quarkus-site-name=ISPN", "--spi-load-balancer-check-remote-poll-interval=500", - "-Dkc.cache-remote-tls-enabled=false", + "-Dkc.cache-remote-create-caches=true", "--verbose" }) void testLoadBalancerCheckFailureWithRemoteOnlyCaches() { @@ -71,7 +84,12 @@ public class ExternalInfinispanTest { } @Test - @Launch({ "start-dev", "--features=multi-site", "--cache=ispn", "--cache-config-file=../../../test-classes/ExternalInfinispan/kcb-infinispan-cache-remote-store-config.xml", "-Djboss.site.name=ISPN" }) + @Launch({ + "start-dev", + "--cache=ispn", + "-Djboss.site.name=ISPN", + "--verbose" + }) void testSiteNameAsSystemProperty(LaunchResult result) { ((CLIResult) result).assertMessage("System property jboss.site.name is in use. Use --spi-connections-infinispan-quarkus-site-name config option instead"); } diff --git a/server-spi-private/src/main/java/org/keycloak/cluster/ManagedCacheManagerProvider.java b/server-spi-private/src/main/java/org/keycloak/cluster/ManagedCacheManagerProvider.java index 3876ffe4e4..6bd92f0b18 100644 --- a/server-spi-private/src/main/java/org/keycloak/cluster/ManagedCacheManagerProvider.java +++ b/server-spi-private/src/main/java/org/keycloak/cluster/ManagedCacheManagerProvider.java @@ -21,15 +21,15 @@ import org.keycloak.Config; /** * A Service Provider Interface (SPI) that allows to plug-in an embedded or remote cache manager instance. - * + * * @author Pedro Igor */ public interface ManagedCacheManagerProvider { - + C getEmbeddedCacheManager(Config.Scope config); /** - * @return A RemoteCacheManager if the feature {@link org.keycloak.common.Profile.Feature#REMOTE_CACHE} is enabled, {@code null} otherwise. + * @return A RemoteCacheManager if the features {@link org.keycloak.common.Profile.Feature#REMOTE_CACHE} or {@link org.keycloak.common.Profile.Feature#MULTI_SITE} is enabled, {@code null} otherwise. */ C getRemoteCacheManager(Config.Scope config); } diff --git a/services/src/test/java/org/keycloak/services/resteasy/ResteasyKeycloakApplication.java b/services/src/test/java/org/keycloak/services/resteasy/ResteasyKeycloakApplication.java index 5ef759c9cb..66268a906f 100644 --- a/services/src/test/java/org/keycloak/services/resteasy/ResteasyKeycloakApplication.java +++ b/services/src/test/java/org/keycloak/services/resteasy/ResteasyKeycloakApplication.java @@ -18,6 +18,7 @@ package org.keycloak.services.resteasy; import org.keycloak.common.Profile; +import org.keycloak.common.util.MultiSiteUtils; import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSessionFactory; import org.keycloak.services.error.KcUnrecognizedPropertyExceptionHandler; @@ -62,7 +63,7 @@ public class ResteasyKeycloakApplication extends KeycloakApplication { singletons.add(new ObjectMapperResolver()); classes.add(WelcomeResource.class); - if (Profile.isFeatureEnabled(Profile.Feature.MULTI_SITE)) { + if (MultiSiteUtils.isMultiSiteEnabled()) { // If we are running in multi-site mode, we need to add a resource which to expose // an endpoint for the load balancer to gather information whether this site should receive requests or not. classes.add(LoadBalancerResource.class); diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/containers/AbstractQuarkusDeployableContainer.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/containers/AbstractQuarkusDeployableContainer.java index d191e0392e..cc50ecba26 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/containers/AbstractQuarkusDeployableContainer.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/containers/AbstractQuarkusDeployableContainer.java @@ -212,7 +212,7 @@ public abstract class AbstractQuarkusDeployableContainer implements DeployableCo addFeaturesOption(commands); var features = getDefaultFeatures(); - if (features.contains("remote-cache") && features.contains("multi-site")) { + if (features.contains("remote-cache") || features.contains("multi-site")) { commands.add("--cache-remote-host=127.0.0.1"); commands.add("--cache-remote-username=keycloak"); commands.add("--cache-remote-password=Password1!"); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/model/AuthenticationSessionProviderTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/model/AuthenticationSessionProviderTest.java index cb23c549fd..2b882c697e 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/model/AuthenticationSessionProviderTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/model/AuthenticationSessionProviderTest.java @@ -25,6 +25,7 @@ import org.junit.Rule; import org.junit.Test; import org.keycloak.common.Profile; import org.keycloak.common.util.Time; +import org.keycloak.infinispan.util.InfinispanUtils; import org.keycloak.models.ClientModel; import org.keycloak.models.Constants; import org.keycloak.models.KeycloakSession; @@ -214,7 +215,7 @@ public class AuthenticationSessionProviderTest extends AbstractTestRealmKeycloak @Test @ModelTest public void testExpiredAuthSessions(KeycloakSession session) { - assumeFalse(Profile.isFeatureEnabled(Profile.Feature.REMOTE_CACHE)); + assumeFalse(InfinispanUtils.isRemoteInfinispan()); AtomicReference authSessionID = new AtomicReference<>(); KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), mainSession -> { diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/AccessTokenTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/AccessTokenTest.java index d5a679bdc9..d583f1d7e5 100755 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/AccessTokenTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/AccessTokenTest.java @@ -175,11 +175,11 @@ public class AccessTokenTest extends AbstractKeycloakTest { testRealms.add(realm); } - + @Test public void loginFormUsernameOrEmailLabel() throws Exception { oauth.openLoginForm(); - + assertEquals("Username or email", driver.findElement(By.xpath("//label[@for='username']")).getText()); } @@ -389,6 +389,8 @@ public class AccessTokenTest extends AbstractKeycloakTest { @Test public void accessTokenCodeExpired() { ProfileAssume.assumeFeatureDisabled(Profile.Feature.REMOTE_CACHE); + ProfileAssume.assumeFeatureDisabled(Profile.Feature.MULTI_SITE); + getTestingClient().testing().setTestingInfinispanTimeService(); RealmManager.realm(adminClient.realm("test")).accessCodeLifeSpan(1); oauth.doLogin("test-user@localhost", "password"); @@ -1323,7 +1325,7 @@ public class AccessTokenTest extends AbstractKeycloakTest { public void accessTokenRequest_ClientEdDSA_RealmEdDSA() throws Exception { conductAccessTokenRequest(Constants.INTERNAL_SIGNATURE_ALGORITHM, Algorithm.EdDSA, Algorithm.EdDSA); } - + @Test public void validateECDSASignatures() { validateTokenECDSASignature(Algorithm.ES256); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/session/LastSessionRefreshUnitTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/session/LastSessionRefreshUnitTest.java index e2578d52db..26e7d424d4 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/session/LastSessionRefreshUnitTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/session/LastSessionRefreshUnitTest.java @@ -66,6 +66,8 @@ public class LastSessionRefreshUnitTest extends AbstractKeycloakTest { @Test public void testLastSessionRefreshCounters() { ProfileAssume.assumeFeatureDisabled(Profile.Feature.REMOTE_CACHE); + ProfileAssume.assumeFeatureDisabled(Profile.Feature.MULTI_SITE); + testingClient.server().run(new LastSessionRefreshServerCounterTest()); } @@ -111,6 +113,8 @@ public class LastSessionRefreshUnitTest extends AbstractKeycloakTest { @Test public void testLastSessionRefreshIntervals() { ProfileAssume.assumeFeatureDisabled(Profile.Feature.REMOTE_CACHE); + ProfileAssume.assumeFeatureDisabled(Profile.Feature.MULTI_SITE); + testingClient.server().run(new LastSessionRefreshServerIntervalsTest()); } diff --git a/testsuite/model/pom.xml b/testsuite/model/pom.xml index a9cd7eb4ed..eba8ea638a 100644 --- a/testsuite/model/pom.xml +++ b/testsuite/model/pom.xml @@ -78,6 +78,12 @@ org.keycloak.testsuite integration-arquillian-tests-base ${project.version} + + + org.keycloak + keycloak-quarkus-server + + ${jdbc.mvn.groupId} @@ -118,6 +124,10 @@ infinispan-component-annotations provided + + org.infinispan + infinispan-remote-query-server + @@ -286,12 +296,6 @@ - - - org.infinispan - infinispan-remote-query-server - - diff --git a/testsuite/model/src/test/java/org/keycloak/testsuite/model/infinispan/CacheExpirationTest.java b/testsuite/model/src/test/java/org/keycloak/testsuite/model/infinispan/CacheExpirationTest.java index 56d089bdc4..08f246634a 100644 --- a/testsuite/model/src/test/java/org/keycloak/testsuite/model/infinispan/CacheExpirationTest.java +++ b/testsuite/model/src/test/java/org/keycloak/testsuite/model/infinispan/CacheExpirationTest.java @@ -1,13 +1,13 @@ /* * Copyright 2020 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. @@ -21,6 +21,8 @@ import org.junit.Assume; import org.junit.Test; import org.keycloak.common.Profile; import org.keycloak.connections.infinispan.InfinispanConnectionProvider; +import org.keycloak.connections.infinispan.InfinispanUtil; +import org.keycloak.infinispan.util.InfinispanUtils; import org.keycloak.models.cache.infinispan.events.AuthenticationSessionAuthNoteUpdateEvent; import org.keycloak.testsuite.model.KeycloakModelTest; import org.keycloak.testsuite.model.RequireProvider; @@ -56,7 +58,7 @@ public class CacheExpirationTest extends KeycloakModelTest { @Test public void testCacheExpiration() throws Exception { - assumeFalse("Embedded caches not available for testing.", Profile.isFeatureEnabled(Profile.Feature.MULTI_SITE) && Profile.isFeatureEnabled(Profile.Feature.REMOTE_CACHE)); + assumeFalse("Embedded caches not available for testing.", InfinispanUtils.isRemoteInfinispan()); log.debugf("Number of previous instances of the class on the heap: %d", getNumberOfInstancesOfClass(AuthenticationSessionAuthNoteUpdateEvent.class)); diff --git a/testsuite/model/src/test/java/org/keycloak/testsuite/model/infinispan/FeatureEnabledTest.java b/testsuite/model/src/test/java/org/keycloak/testsuite/model/infinispan/FeatureEnabledTest.java index d29419f305..99f484d7c5 100644 --- a/testsuite/model/src/test/java/org/keycloak/testsuite/model/infinispan/FeatureEnabledTest.java +++ b/testsuite/model/src/test/java/org/keycloak/testsuite/model/infinispan/FeatureEnabledTest.java @@ -23,6 +23,7 @@ import java.util.function.Predicate; import org.infinispan.commons.CacheConfigurationException; import org.junit.Test; import org.keycloak.common.Profile; +import org.keycloak.common.util.MultiSiteUtils; import org.keycloak.connections.infinispan.InfinispanConnectionProvider; import org.keycloak.infinispan.util.InfinispanUtils; import org.keycloak.testsuite.model.KeycloakModelTest; @@ -60,8 +61,7 @@ public class FeatureEnabledTest extends KeycloakModelTest { @Test public void testRemoteCachesOnly() { - assumeTrue("Remote-Cache Feature disabled", Profile.isFeatureEnabled(Profile.Feature.REMOTE_CACHE)); - assumeTrue("Multi-Site Feature disabled", Profile.isFeatureEnabled(Profile.Feature.MULTI_SITE)); + assumeTrue("Remote-Cache Feature disabled", Profile.isFeatureEnabled(Profile.Feature.REMOTE_CACHE) || MultiSiteUtils.isMultiSiteEnabled()); assertTrue(InfinispanUtils.isRemoteInfinispan()); assertFalse(InfinispanUtils.isEmbeddedInfinispan()); inComittedTransaction(session -> { @@ -72,22 +72,9 @@ public class FeatureEnabledTest extends KeycloakModelTest { }); } - @Test - public void testRemoteAndEmbeddedCaches() { - assumeTrue("Multi-Site Feature disabled", Profile.isFeatureEnabled(Profile.Feature.MULTI_SITE)); - assumeFalse("Remote-Cache Feature enabled", Profile.isFeatureEnabled(Profile.Feature.REMOTE_CACHE)); - assertFalse(InfinispanUtils.isRemoteInfinispan()); - assertTrue(InfinispanUtils.isEmbeddedInfinispan()); - inComittedTransaction(session -> { - var clusterProvider = session.getProvider(InfinispanConnectionProvider.class); - Arrays.stream(CLUSTERED_CACHE_NAMES).forEach(s -> assertEmbeddedCacheExists(clusterProvider, s)); - Arrays.stream(CLUSTERED_CACHE_NAMES).forEach(s -> assertRemoteCacheExists(clusterProvider, s)); - }); - } - @Test public void testEmbeddedCachesOnly() { - assumeFalse("Multi-Site Feature enabled", Profile.isFeatureEnabled(Profile.Feature.MULTI_SITE)); + assumeFalse("Multi-Site Feature enabled", MultiSiteUtils.isMultiSiteEnabled()); assumeFalse("Remote-Cache Feature enabled", Profile.isFeatureEnabled(Profile.Feature.REMOTE_CACHE)); assertFalse(InfinispanUtils.isRemoteInfinispan()); assertTrue(InfinispanUtils.isEmbeddedInfinispan()); diff --git a/testsuite/model/src/test/java/org/keycloak/testsuite/model/parameters/CrossDCInfinispan.java b/testsuite/model/src/test/java/org/keycloak/testsuite/model/parameters/CrossDCInfinispan.java index 955bdd8df3..11e8bb5c1a 100644 --- a/testsuite/model/src/test/java/org/keycloak/testsuite/model/parameters/CrossDCInfinispan.java +++ b/testsuite/model/src/test/java/org/keycloak/testsuite/model/parameters/CrossDCInfinispan.java @@ -25,6 +25,7 @@ import org.keycloak.testsuite.model.HotRodServerRule; import org.keycloak.testsuite.model.KeycloakModelParameters; import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; import java.util.stream.Stream; /** @@ -66,7 +67,7 @@ public class CrossDCInfinispan extends KeycloakModelParameters { } public CrossDCInfinispan() { - super(Infinispan.ALLOWED_SPIS, Infinispan.ALLOWED_FACTORIES); + super(Infinispan.ALLOWED_SPIS, Stream.concat(Infinispan.ALLOWED_FACTORIES.stream(), RemoteInfinispan.ALLOWED_FACTORIES.stream()).collect(Collectors.toSet())); } @Override diff --git a/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/OfflineSessionPersistenceTest.java b/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/OfflineSessionPersistenceTest.java index 732b683b61..d4319942e2 100644 --- a/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/OfflineSessionPersistenceTest.java +++ b/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/OfflineSessionPersistenceTest.java @@ -37,6 +37,7 @@ import java.util.stream.Stream; import org.hamcrest.Matchers; import org.infinispan.commons.CacheException; import org.junit.Test; +import org.keycloak.infinispan.util.InfinispanUtils; import org.keycloak.models.AuthenticatedClientSessionModel; import org.keycloak.models.ClientModel; import org.keycloak.models.Constants; @@ -50,13 +51,13 @@ import org.keycloak.models.UserSessionProvider; import org.keycloak.models.session.UserSessionPersisterProvider; import org.keycloak.models.sessions.infinispan.InfinispanUserSessionProvider; import org.keycloak.models.sessions.infinispan.PersistentUserSessionProvider; -import org.keycloak.models.sessions.infinispan.remote.RemoteUserSessionProvider; import org.keycloak.services.managers.RealmManager; import org.keycloak.testsuite.model.KeycloakModelTest; import org.keycloak.testsuite.model.RequireProvider; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; +import static org.junit.Assume.assumeTrue; /** * @@ -252,6 +253,8 @@ public class OfflineSessionPersistenceTest extends KeycloakModelTest { @Test @RequireProvider(UserSessionPersisterProvider.class) public void testOfflineSessionLoadingAfterCacheRemoval() { + assumeTrue("Run only if Embedded Infinispan is used for storing/caching sessions.", InfinispanUtils.isEmbeddedInfinispan()); + List offlineSessionIds = createOfflineSessions(realmId, userIds); assertOfflineSessionsExist(realmId, offlineSessionIds); @@ -268,8 +271,6 @@ public class OfflineSessionPersistenceTest extends KeycloakModelTest { ((InfinispanUserSessionProvider) provider).removeLocalUserSessions(realm.getId(), true); } else if (provider instanceof PersistentUserSessionProvider) { ((PersistentUserSessionProvider) provider).removeLocalUserSessions(realm.getId(), true); - } else if (provider instanceof RemoteUserSessionProvider) { - //no-op, session not local } else { throw new IllegalStateException("Unknown UserSessionProvider: " + provider); } diff --git a/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/SessionTimeoutsTest.java b/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/SessionTimeoutsTest.java index dea0adb454..01e7585149 100644 --- a/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/SessionTimeoutsTest.java +++ b/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/SessionTimeoutsTest.java @@ -26,7 +26,7 @@ import org.junit.FixMethodOrder; import org.junit.Test; import org.junit.rules.TestRule; import org.junit.runners.MethodSorters; -import org.keycloak.common.Profile; +import org.keycloak.common.util.MultiSiteUtils; import org.keycloak.common.util.Retry; import org.keycloak.common.util.Time; import org.keycloak.connections.infinispan.InfinispanConnectionProvider; @@ -298,7 +298,7 @@ public class SessionTimeoutsTest extends KeycloakModelTest { return null; }); - if (Profile.isFeatureEnabled(Profile.Feature.PERSISTENT_USER_SESSIONS)) { + if (MultiSiteUtils.isPersistentSessionsEnabled()) { // The persistent session will write the update data asynchronously, wait for it to arrive. Retry.executeWithBackoff(iteration -> { withRealm(realmId, (session, realm) -> { diff --git a/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/UserSessionInitializerTest.java b/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/UserSessionInitializerTest.java index 88ba4a359d..78d64967cb 100644 --- a/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/UserSessionInitializerTest.java +++ b/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/UserSessionInitializerTest.java @@ -28,6 +28,7 @@ import org.infinispan.Cache; import org.infinispan.client.hotrod.RemoteCache; import org.junit.Assert; import org.junit.Test; +import org.keycloak.common.util.MultiSiteUtils; import org.keycloak.connections.infinispan.InfinispanConnectionProvider; import org.keycloak.infinispan.util.InfinispanUtils; import org.keycloak.models.ClientModel; @@ -48,6 +49,7 @@ import org.keycloak.testsuite.model.RequireProvider; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Every.everyItem; import static org.hamcrest.core.Is.is; +import static org.junit.Assume.assumeFalse; import static org.keycloak.connections.infinispan.InfinispanConnectionProvider.USER_SESSION_CACHE_NAME; /** @@ -157,6 +159,7 @@ public class UserSessionInitializerTest extends KeycloakModelTest { @Test public void testUserSessionPropagationBetweenSites() throws InterruptedException { + assumeFalse("Run only if Infinispan caches are used for storing/caching sessions", MultiSiteUtils.isMultiSiteEnabled() && MultiSiteUtils.isPersistentSessionsEnabled()); AtomicInteger index = new AtomicInteger(); AtomicReference userSessionId = new AtomicReference<>(); AtomicReference> containsSession = new AtomicReference<>(new LinkedList<>()); diff --git a/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/UserSessionPersisterProviderTest.java b/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/UserSessionPersisterProviderTest.java index 9ffb9d57d8..c6e0687a20 100644 --- a/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/UserSessionPersisterProviderTest.java +++ b/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/UserSessionPersisterProviderTest.java @@ -21,7 +21,7 @@ import org.junit.Assert; import org.junit.Assume; import org.junit.Test; import org.keycloak.OAuth2Constants; -import org.keycloak.common.Profile; +import org.keycloak.common.util.MultiSiteUtils; import org.keycloak.common.util.Time; import org.keycloak.infinispan.util.InfinispanUtils; import org.keycloak.models.AuthenticatedClientSessionModel; @@ -151,7 +151,7 @@ public class UserSessionPersisterProviderTest extends KeycloakModelTest { .forEach(userSessionLooper -> persistUserSession(session, userSessionLooper, true)); }); - if (!Profile.isFeatureEnabled(Profile.Feature.PERSISTENT_USER_SESSIONS)) { + if (!MultiSiteUtils.isPersistentSessionsEnabled()) { inComittedTransaction(session -> { // Persist 1 online session RealmModel realm = session.realms().getRealm(realmId); @@ -581,7 +581,8 @@ public class UserSessionPersisterProviderTest extends KeycloakModelTest { @Test public void testMigrateSession() { - Assume.assumeTrue(Profile.isFeatureEnabled(Profile.Feature.PERSISTENT_USER_SESSIONS)); + Assume.assumeTrue(MultiSiteUtils.isPersistentSessionsEnabled()); + Assume.assumeTrue(InfinispanUtils.isEmbeddedInfinispan()); UserSessionModel[] sessions = inComittedTransaction(session -> { // Create some sessions in infinispan diff --git a/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/UserSessionProviderModelTest.java b/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/UserSessionProviderModelTest.java index 63b86dde2f..dd7dd80dc2 100644 --- a/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/UserSessionProviderModelTest.java +++ b/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/UserSessionProviderModelTest.java @@ -20,6 +20,7 @@ import org.hamcrest.Matchers; import org.junit.Assert; import org.junit.Test; import org.keycloak.common.Profile; +import org.keycloak.common.util.MultiSiteUtils; import org.keycloak.models.AuthenticatedClientSessionModel; import org.keycloak.models.ClientModel; import org.keycloak.models.Constants; @@ -129,7 +130,7 @@ public class UserSessionProviderModelTest extends KeycloakModelTest { // skip for persistent user sessions as the periodic task is not used there TimerProvider timer = kcSession.getProvider(TimerProvider.class); TimerProvider.TimerTaskContext timerTaskCtx = null; - if (timer != null && !Profile.isFeatureEnabled(Profile.Feature.PERSISTENT_USER_SESSIONS)) { + if (timer != null && !MultiSiteUtils.isPersistentSessionsEnabled()) { timerTaskCtx = timer.cancelTask(PersisterLastSessionRefreshStoreFactory.DB_LSR_PERIODIC_TASK_NAME); log.info("Cancelled periodic task " + PersisterLastSessionRefreshStoreFactory.DB_LSR_PERIODIC_TASK_NAME); } @@ -181,7 +182,7 @@ public class UserSessionProviderModelTest extends KeycloakModelTest { setTimeOffset(0); kcSession.getKeycloakSessionFactory().publish(new ResetTimeOffsetEvent()); // Enable periodic task again, skip for persistent user sessions as the periodic task is not used there - if (timer != null && timerTaskCtx != null && !Profile.isFeatureEnabled(Profile.Feature.PERSISTENT_USER_SESSIONS)) { + if (timer != null && timerTaskCtx != null && !MultiSiteUtils.isPersistentSessionsEnabled()) { timer.schedule(timerTaskCtx.getRunnable(), timerTaskCtx.getIntervalMillis(), PersisterLastSessionRefreshStoreFactory.DB_LSR_PERIODIC_TASK_NAME); } diff --git a/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/UserSessionProviderOfflineModelTest.java b/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/UserSessionProviderOfflineModelTest.java index 5f6c501aa1..9d109e7d38 100644 --- a/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/UserSessionProviderOfflineModelTest.java +++ b/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/UserSessionProviderOfflineModelTest.java @@ -41,6 +41,7 @@ import org.junit.Assert; import org.junit.Assume; import org.junit.Test; import org.keycloak.common.Profile; +import org.keycloak.common.util.MultiSiteUtils; import org.keycloak.common.util.Time; import org.keycloak.connections.infinispan.InfinispanConnectionProvider; import org.keycloak.infinispan.util.InfinispanUtils; @@ -126,7 +127,7 @@ public class UserSessionProviderOfflineModelTest extends KeycloakModelTest { // skip for persistent user sessions as the periodic task is not used there TimerProvider timer = kcSession.getProvider(TimerProvider.class); TimerProvider.TimerTaskContext timerTaskCtx = null; - if (timer != null && !Profile.isFeatureEnabled(Profile.Feature.PERSISTENT_USER_SESSIONS)) { + if (timer != null && !MultiSiteUtils.isPersistentSessionsEnabled()) { timerTaskCtx = timer.cancelTask(PersisterLastSessionRefreshStoreFactory.DB_LSR_PERIODIC_TASK_NAME); log.info("Cancelled periodic task " + PersisterLastSessionRefreshStoreFactory.DB_LSR_PERIODIC_TASK_NAME); } @@ -245,7 +246,7 @@ public class UserSessionProviderOfflineModelTest extends KeycloakModelTest { setTimeOffset(0); kcSession.getKeycloakSessionFactory().publish(new ResetTimeOffsetEvent()); // Enable periodic task again, skip for persistent user sessions as the periodic task is not used there - if (timer != null && timerTaskCtx != null && !Profile.isFeatureEnabled(Profile.Feature.PERSISTENT_USER_SESSIONS)) { + if (timer != null && timerTaskCtx != null && !MultiSiteUtils.isPersistentSessionsEnabled()) { timer.schedule(timerTaskCtx.getRunnable(), timerTaskCtx.getIntervalMillis(), PersisterLastSessionRefreshStoreFactory.DB_LSR_PERIODIC_TASK_NAME); } @@ -259,7 +260,7 @@ public class UserSessionProviderOfflineModelTest extends KeycloakModelTest { // skip for persistent user sessions as the periodic task is not used there TimerProvider timer = kcSession.getProvider(TimerProvider.class); TimerProvider.TimerTaskContext timerTaskCtx = null; - if (timer != null && !Profile.isFeatureEnabled(Profile.Feature.PERSISTENT_USER_SESSIONS)) { + if (timer != null && !MultiSiteUtils.isPersistentSessionsEnabled()) { timerTaskCtx = timer.cancelTask(PersisterLastSessionRefreshStoreFactory.DB_LSR_PERIODIC_TASK_NAME); log.info("Cancelled periodic task " + PersisterLastSessionRefreshStoreFactory.DB_LSR_PERIODIC_TASK_NAME); } @@ -314,14 +315,14 @@ public class UserSessionProviderOfflineModelTest extends KeycloakModelTest { session.sessions().createOfflineUserSession(userSession); session.sessions().createOfflineUserSession(origSessions[0]); - if (!Profile.isFeatureEnabled(Profile.Feature.PERSISTENT_USER_SESSIONS) && InfinispanUtils.isEmbeddedInfinispan()) { + if (!MultiSiteUtils.isPersistentSessionsEnabled() && InfinispanUtils.isEmbeddedInfinispan()) { // This does not work with persistent user sessions because we currently have two transactions and the one that creates the offline user sessions is not committing the changes // try to load user session from persister Assert.assertEquals(2, persister.loadUserSessionsStream(0, 10, true, "00000000-0000-0000-0000-000000000000").count()); } }); - if (Profile.isFeatureEnabled(Profile.Feature.PERSISTENT_USER_SESSIONS) && InfinispanUtils.isEmbeddedInfinispan()) { + if (MultiSiteUtils.isPersistentSessionsEnabled() && InfinispanUtils.isEmbeddedInfinispan()) { inComittedTransaction(session -> { persister = session.getProvider(UserSessionPersisterProvider.class); Assert.assertEquals(2, persister.loadUserSessionsStream(0, 10, true, "00000000-0000-0000-0000-000000000000").count()); @@ -333,7 +334,7 @@ public class UserSessionProviderOfflineModelTest extends KeycloakModelTest { kcSession.getKeycloakSessionFactory().publish(new ResetTimeOffsetEvent()); // Enable periodic task again, skip for persistent user sessions as the periodic task is not used there - if (timer != null && timerTaskCtx != null && !Profile.isFeatureEnabled(Profile.Feature.PERSISTENT_USER_SESSIONS)) { + if (timer != null && timerTaskCtx != null && !MultiSiteUtils.isPersistentSessionsEnabled()) { timer.schedule(timerTaskCtx.getRunnable(), timerTaskCtx.getIntervalMillis(), PersisterLastSessionRefreshStoreFactory.DB_LSR_PERIODIC_TASK_NAME); } @@ -502,7 +503,7 @@ public class UserSessionProviderOfflineModelTest extends KeycloakModelTest { // skip the test for CrossDC Assume.assumeFalse(Objects.equals(CONFIG.scope("connectionsInfinispan.default").get("remoteStoreEnabled"), "true")); // As offline session's timeout is not overriden when PERSISTENT_USER_SESSIONS is enabled - Assume.assumeFalse(Profile.isFeatureEnabled(Profile.Feature.PERSISTENT_USER_SESSIONS)); + Assume.assumeFalse(MultiSiteUtils.isPersistentSessionsEnabled()); createOfflineSessions("user1", 2, new LinkedList<>(), new LinkedList<>());