keycloak-uncached
Changes
forms/common-themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties 4(+2 -2)
integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ServerInfoResource.java 20(+20 -0)
model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/ClientAdapter.java 2(+1 -1)
model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanCacheRealmProviderFactory.java 113(+110 -3)
model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanCacheUserProviderFactory.java 2(+1 -1)
model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanRealmCache.java 24(+13 -11)
model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanUserCache.java 7(+4 -3)
model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmCache.java 2(+2 -0)
Details
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties b/forms/common-themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties
index b92f65b..eca236f 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties
+++ b/forms/common-themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties
@@ -63,9 +63,9 @@ supported-locales=Supported Locales
supported-locales.placeholder=Type a locale and enter
default-locale=Default Locale
realm-cache-enabled=Realm Cache Enabled
-realm-cache-enabled.tooltip=Enable/disable cache for realm, client and role data.
+realm-cache-enabled.tooltip=Enable/disable cache for realms, clients and roles.
user-cache-enabled=User Cache Enabled
-user-cache-enabled.tooltip=Enable/disable user and user role mapping cache.
+user-cache-enabled.tooltip=Enable/disable cache for users and user role mappings.
revoke-refresh-token=Revoke Refresh Token
revoke-refresh-token.tooltip=If enabled refresh tokens can only be used once. Otherwise refresh tokens are not revoked when used and can be used multiple times.
sso-session-idle=SSO Session Idle
diff --git a/integration/admin-client/src/main/java/org/keycloak/admin/client/Keycloak.java b/integration/admin-client/src/main/java/org/keycloak/admin/client/Keycloak.java
index 431a646..bc75fa9 100755
--- a/integration/admin-client/src/main/java/org/keycloak/admin/client/Keycloak.java
+++ b/integration/admin-client/src/main/java/org/keycloak/admin/client/Keycloak.java
@@ -6,6 +6,7 @@ import org.jboss.resteasy.client.jaxrs.ResteasyWebTarget;
import org.keycloak.admin.client.resource.BearerAuthFilter;
import org.keycloak.admin.client.resource.RealmResource;
import org.keycloak.admin.client.resource.RealmsResource;
+import org.keycloak.admin.client.resource.ServerInfoResource;
import org.keycloak.admin.client.token.TokenManager;
/**
@@ -51,6 +52,10 @@ public class Keycloak {
return realms().realm(realmName);
}
+ public ServerInfoResource serverInfo(){
+ return target.proxy(ServerInfoResource.class);
+ }
+
public TokenManager tokenManager(){
return tokenManager;
}
diff --git a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ServerInfoResource.java b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ServerInfoResource.java
new file mode 100644
index 0000000..6ebd642
--- /dev/null
+++ b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ServerInfoResource.java
@@ -0,0 +1,20 @@
+package org.keycloak.admin.client.resource;
+
+import org.keycloak.representations.info.ServerInfoRepresentation;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+@Path("/admin/serverinfo")
+public interface ServerInfoResource {
+
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ ServerInfoRepresentation getInfo();
+
+}
diff --git a/model/api/src/main/java/org/keycloak/models/OTPPolicy.java b/model/api/src/main/java/org/keycloak/models/OTPPolicy.java
index 1c6665a..157842e 100755
--- a/model/api/src/main/java/org/keycloak/models/OTPPolicy.java
+++ b/model/api/src/main/java/org/keycloak/models/OTPPolicy.java
@@ -4,6 +4,7 @@ import org.jboss.logging.Logger;
import org.keycloak.models.utils.Base32;
import org.keycloak.models.utils.HmacOTP;
+import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
@@ -13,7 +14,7 @@ import java.util.Map;
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
-public class OTPPolicy {
+public class OTPPolicy implements Serializable {
protected static final Logger logger = Logger.getLogger(OTPPolicy.class);
diff --git a/model/api/src/main/java/org/keycloak/models/RequiredActionProviderModel.java b/model/api/src/main/java/org/keycloak/models/RequiredActionProviderModel.java
index e1c356b..0ecf878 100755
--- a/model/api/src/main/java/org/keycloak/models/RequiredActionProviderModel.java
+++ b/model/api/src/main/java/org/keycloak/models/RequiredActionProviderModel.java
@@ -1,5 +1,6 @@
package org.keycloak.models;
+import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
@@ -7,7 +8,7 @@ import java.util.Map;
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
-public class RequiredActionProviderModel {
+public class RequiredActionProviderModel implements Serializable {
private String id;
private String alias;
diff --git a/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/ClientAdapter.java b/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/ClientAdapter.java
index 20c8725..2f7e61f 100755
--- a/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/ClientAdapter.java
+++ b/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/ClientAdapter.java
@@ -29,7 +29,7 @@ public class ClientAdapter implements ClientModel {
private void getDelegateForUpdate() {
if (updated == null) {
cacheSession.registerApplicationInvalidation(getId());
- updated = updated = cacheSession.getDelegate().getClientById(getId(), cachedRealm);
+ updated = cacheSession.getDelegate().getClientById(getId(), cachedRealm);
if (updated == null) throw new IllegalStateException("Not found in database");
}
}
diff --git a/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanCacheRealmProviderFactory.java b/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanCacheRealmProviderFactory.java
index 4b96241..5a76153 100755
--- a/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanCacheRealmProviderFactory.java
+++ b/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanCacheRealmProviderFactory.java
@@ -1,6 +1,16 @@
package org.keycloak.models.cache.infinispan;
import org.infinispan.Cache;
+import org.infinispan.notifications.Listener;
+import org.infinispan.notifications.cachelistener.annotation.CacheEntriesEvicted;
+import org.infinispan.notifications.cachelistener.annotation.CacheEntryCreated;
+import org.infinispan.notifications.cachelistener.annotation.CacheEntryInvalidated;
+import org.infinispan.notifications.cachelistener.annotation.CacheEntryRemoved;
+import org.infinispan.notifications.cachelistener.event.CacheEntriesEvictedEvent;
+import org.infinispan.notifications.cachelistener.event.CacheEntryCreatedEvent;
+import org.infinispan.notifications.cachelistener.event.CacheEntryInvalidatedEvent;
+import org.infinispan.notifications.cachelistener.event.CacheEntryRemovedEvent;
+import org.jboss.logging.Logger;
import org.keycloak.Config;
import org.keycloak.connections.infinispan.InfinispanConnectionProvider;
import org.keycloak.models.KeycloakSession;
@@ -8,6 +18,8 @@ import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.cache.CacheRealmProvider;
import org.keycloak.models.cache.CacheRealmProviderFactory;
import org.keycloak.models.cache.RealmCache;
+import org.keycloak.models.cache.entities.CachedRealm;
+import org.keycloak.models.cache.entities.CachedUser;
import java.util.concurrent.ConcurrentHashMap;
@@ -17,15 +29,43 @@ import java.util.concurrent.ConcurrentHashMap;
*/
public class InfinispanCacheRealmProviderFactory implements CacheRealmProviderFactory {
- protected final ConcurrentHashMap<String, String> realmLookup = new ConcurrentHashMap<String, String>();
+ private static final Logger log = Logger.getLogger(InfinispanCacheRealmProviderFactory.class);
+
+ protected volatile InfinispanRealmCache realmCache;
+
+ protected final ConcurrentHashMap<String, String> realmLookup = new ConcurrentHashMap<>();
+
+ private boolean isNewInfinispan;
@Override
public CacheRealmProvider create(KeycloakSession session) {
- Cache<String, Object> cache = session.getProvider(InfinispanConnectionProvider.class).getCache(InfinispanConnectionProvider.REALM_CACHE_NAME);
- RealmCache realmCache = new InfinispanRealmCache(cache, realmLookup);
+ lazyInit(session);
return new DefaultCacheRealmProvider(realmCache, session);
}
+ private void lazyInit(KeycloakSession session) {
+ if (realmCache == null) {
+ synchronized (this) {
+ if (realmCache == null) {
+ checkIspnVersion();
+
+ Cache<String, Object> cache = session.getProvider(InfinispanConnectionProvider.class).getCache(InfinispanConnectionProvider.REALM_CACHE_NAME);
+ cache.addListener(new CacheListener());
+ realmCache = new InfinispanRealmCache(cache, realmLookup);
+ }
+ }
+ }
+ }
+
+ protected void checkIspnVersion() {
+ try {
+ CacheEntryCreatedEvent.class.getMethod("getValue");
+ isNewInfinispan = true;
+ } catch (NoSuchMethodException nsme) {
+ isNewInfinispan = false;
+ }
+ }
+
@Override
public void init(Config.Scope config) {
}
@@ -44,4 +84,71 @@ public class InfinispanCacheRealmProviderFactory implements CacheRealmProviderFa
return "infinispan";
}
+ @Listener
+ public class CacheListener {
+
+ @CacheEntryCreated
+ public void created(CacheEntryCreatedEvent<String, Object> event) {
+ if (!event.isPre()) {
+ Object object;
+
+ // Try optimized version if available
+ if (isNewInfinispan) {
+ object = event.getValue();
+ } else {
+ String id = event.getKey();
+ object = event.getCache().get(id);
+ }
+
+ if (object != null) {
+ if (object instanceof CachedRealm) {
+ CachedRealm realm = (CachedRealm) object;
+ realmLookup.put(realm.getName(), realm.getId());
+ log.tracev("Realm added realm={0}", realm.getName());
+ }
+ }
+ }
+ }
+
+ @CacheEntryRemoved
+ public void removed(CacheEntryRemovedEvent<String, Object> event) {
+ if (event.isPre()) {
+ Object object = event.getValue();
+ if (object != null) {
+ remove(object);
+ }
+ }
+ }
+
+ @CacheEntryInvalidated
+ public void removed(CacheEntryInvalidatedEvent<String, Object> event) {
+ if (event.isPre()) {
+ Object object = event.getValue();
+ if (object != null) {
+ remove(object);
+ }
+ }
+ }
+
+ @CacheEntriesEvicted
+ public void userEvicted(CacheEntriesEvictedEvent<String, Object> event) {
+ for (Object object : event.getEntries().values()) {
+ remove(object);
+ }
+ }
+
+ private void remove(Object object) {
+ if (object instanceof CachedRealm) {
+ CachedRealm realm = (CachedRealm) object;
+
+ realmLookup.remove(realm.getName());
+
+ for (String c : realm.getClients().values()) {
+ realmCache.evictCachedApplicationById(c);
+ }
+
+ log.tracev("Realm removed realm={0}", realm.getName());
+ }
+ }
+ }
}
diff --git a/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanCacheUserProviderFactory.java b/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanCacheUserProviderFactory.java
index 4eb0bdf..ec69912 100755
--- a/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanCacheUserProviderFactory.java
+++ b/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanCacheUserProviderFactory.java
@@ -26,7 +26,7 @@ public class InfinispanCacheUserProviderFactory implements CacheUserProviderFact
private static final Logger log = Logger.getLogger(InfinispanCacheUserProviderFactory.class);
- protected InfinispanUserCache userCache;
+ protected volatile InfinispanUserCache userCache;
protected final RealmLookup usernameLookup = new RealmLookup();
diff --git a/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanRealmCache.java b/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanRealmCache.java
index a5239fb..8155801 100755
--- a/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanRealmCache.java
+++ b/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanRealmCache.java
@@ -38,9 +38,10 @@ public class InfinispanRealmCache implements RealmCache {
@Override
public void setEnabled(boolean enabled) {
- clear();
+ if (this.enabled && !enabled) {
+ clear();
+ }
this.enabled = enabled;
- clear();
}
@Override
@@ -66,7 +67,7 @@ public class InfinispanRealmCache implements RealmCache {
public void addCachedRealm(CachedRealm realm) {
if (!enabled) return;
logger.tracev("Adding realm {0}", realm.getId());
- cache.put(realm.getId(), realm);
+ cache.putForExternalRead(realm.getId(), realm);
realmLookup.put(realm.getName(), realm.getId());
}
@@ -93,7 +94,7 @@ public class InfinispanRealmCache implements RealmCache {
public void addCachedClient(CachedClient app) {
if (!enabled) return;
logger.tracev("Adding application {0}", app.getId());
- cache.put(app.getId(), app);
+ cache.putForExternalRead(app.getId(), app);
}
@Override
@@ -103,6 +104,12 @@ public class InfinispanRealmCache implements RealmCache {
}
@Override
+ public void evictCachedApplicationById(String id) {
+ logger.tracev("Evicting application {0}", id);
+ cache.evict(id);
+ }
+
+ @Override
public CachedGroup getGroup(String id) {
if (!enabled) return null;
return get(id, CachedGroup.class);
@@ -112,15 +119,13 @@ public class InfinispanRealmCache implements RealmCache {
public void invalidateGroup(CachedGroup role) {
logger.tracev("Removing group {0}", role.getId());
cache.remove(role.getId());
-
}
@Override
public void addCachedGroup(CachedGroup role) {
if (!enabled) return;
logger.tracev("Adding group {0}", role.getId());
- cache.put(role.getId(), role);
-
+ cache.putForExternalRead(role.getId(), role);
}
@Override
@@ -134,7 +139,6 @@ public class InfinispanRealmCache implements RealmCache {
public void invalidateGroupById(String id) {
logger.tracev("Removing group {0}", id);
cache.remove(id);
-
}
@Override
@@ -143,8 +147,6 @@ public class InfinispanRealmCache implements RealmCache {
return get(id, CachedRole.class);
}
-
-
@Override
public void invalidateRole(CachedRole role) {
logger.tracev("Removing role {0}", role.getId());
@@ -161,7 +163,7 @@ public class InfinispanRealmCache implements RealmCache {
public void addCachedRole(CachedRole role) {
if (!enabled) return;
logger.tracev("Adding role {0}", role.getId());
- cache.put(role.getId(), role);
+ cache.putForExternalRead(role.getId(), role);
}
@Override
diff --git a/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanUserCache.java b/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanUserCache.java
index fbb36c5..c5e960c 100755
--- a/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanUserCache.java
+++ b/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanUserCache.java
@@ -35,9 +35,10 @@ public class InfinispanUserCache implements UserCache {
@Override
public void setEnabled(boolean enabled) {
- clear();
+ if (this.enabled && !enabled) {
+ clear();
+ }
this.enabled = enabled;
- clear();
}
@Override
@@ -62,7 +63,7 @@ public class InfinispanUserCache implements UserCache {
@Override
public void addCachedUser(String realmId, CachedUser user) {
logger.tracev("Adding user {0}", user.getId());
- cache.put(user.getId(), user);
+ cache.putForExternalRead(user.getId(), user);
}
@Override
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmCache.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmCache.java
index df74b53..007daac 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmCache.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmCache.java
@@ -26,6 +26,8 @@ public interface RealmCache {
void invalidateApplication(CachedClient app);
+ void evictCachedApplicationById(String id);
+
void addCachedClient(CachedClient app);
void invalidateCachedApplicationById(String id);
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/info/ServerInfoAdminResource.java b/services/src/main/java/org/keycloak/services/resources/admin/info/ServerInfoAdminResource.java
index 660b1c4..672745c 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/info/ServerInfoAdminResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/info/ServerInfoAdminResource.java
@@ -31,6 +31,7 @@ import org.keycloak.provider.Spi;
import org.keycloak.representations.idm.ConfigPropertyRepresentation;
import org.keycloak.representations.idm.ProtocolMapperRepresentation;
import org.keycloak.representations.idm.ProtocolMapperTypeRepresentation;
+import org.keycloak.representations.info.*;
import org.keycloak.social.SocialIdentityProvider;
/**
@@ -51,7 +52,7 @@ public class ServerInfoAdminResource {
@GET
public ServerInfoRepresentation getInfo() {
ServerInfoRepresentation info = new ServerInfoRepresentation();
- info.setSystemInfo(SystemInfoRepresentation.create(session));
+ info.setSystemInfo(SystemInfoRepresentation.create(session.getKeycloakSessionFactory().getServerStartupTimestamp()));
info.setMemoryInfo(MemoryInfoRepresentation.create());
setSocialProviders(info);
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/ClientTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/ClientTest.java
index dd575b1..31f88bc 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/ClientTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/ClientTest.java
@@ -1,24 +1,26 @@
package org.keycloak.testsuite.admin;
+import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import org.keycloak.admin.client.resource.ClientResource;
import org.keycloak.admin.client.resource.ProtocolMappersResource;
import org.keycloak.models.Constants;
import org.keycloak.protocol.oidc.OIDCLoginProtocolFactory;
-import org.keycloak.representations.idm.ClientRepresentation;
-import org.keycloak.representations.idm.ProtocolMapperRepresentation;
-import org.keycloak.representations.idm.RoleRepresentation;
-import org.keycloak.representations.idm.UserSessionRepresentation;
+import org.keycloak.representations.idm.*;
import org.keycloak.testsuite.OAuthClient;
import org.keycloak.testsuite.rule.WebResource;
import org.keycloak.testsuite.rule.WebRule;
import org.openqa.selenium.WebDriver;
import javax.ws.rs.NotFoundException;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Response;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
@@ -46,19 +48,21 @@ public class ClientTest extends AbstractClientTest {
assertNames(realm.clients().findAll(), "account", "realm-management", "security-admin-console", "broker", Constants.ADMIN_CLI_CLIENT_ID);
}
- private String createClient() {
+ private ClientRepresentation createClient() {
ClientRepresentation rep = new ClientRepresentation();
rep.setClientId("my-app");
rep.setDescription("my-app description");
rep.setEnabled(true);
Response response = realm.clients().create(rep);
response.close();
- return ApiUtil.getCreatedId(response);
+ String id = ApiUtil.getCreatedId(response);
+ rep.setId(id);
+ return rep;
}
@Test
public void createClientVerify() {
- String id = createClient();
+ String id = createClient().getId();
assertNotNull(realm.clients().get(id));
assertNames(realm.clients().findAll(), "account", "realm-management", "security-admin-console", "broker", "my-app", Constants.ADMIN_CLI_CLIENT_ID);
@@ -66,14 +70,14 @@ public class ClientTest extends AbstractClientTest {
@Test
public void removeClient() {
- String id = createClient();
+ String id = createClient().getId();
realm.clients().get(id).remove();
}
@Test
public void getClientRepresentation() {
- String id = createClient();
+ String id = createClient().getId();
ClientRepresentation rep = realm.clients().get(id).toRepresentation();
assertEquals(id, rep.getId());
@@ -86,8 +90,7 @@ public class ClientTest extends AbstractClientTest {
*/
@Test
public void getClientDescription() {
-
- String id = createClient();
+ String id = createClient().getId();
ClientRepresentation rep = realm.clients().get(id).toRepresentation();
assertEquals(id, rep.getId());
@@ -145,6 +148,28 @@ public class ClientTest extends AbstractClientTest {
protocolMappersTest(mappersResource);
}
+ @Test
+ public void updateClient() {
+ ClientRepresentation client = createClient();
+
+ ClientRepresentation newClient = new ClientRepresentation();
+ newClient.setId(client.getId());
+ newClient.setClientId(client.getClientId());
+ newClient.setBaseUrl("http://baseurl");
+
+ realm.clients().get(client.getId()).update(newClient);
+
+ ClientRepresentation storedClient = realm.clients().get(client.getId()).toRepresentation();
+
+ assertClient(client, storedClient);
+
+ newClient.setSecret("new-secret");
+
+ realm.clients().get(client.getId()).update(newClient);
+
+ storedClient = realm.clients().get(client.getId()).toRepresentation();
+ assertClient(client, storedClient);
+ }
public static void protocolMappersTest(ProtocolMappersResource mappersResource) {
// assert default mappers found
@@ -197,4 +222,62 @@ public class ClientTest extends AbstractClientTest {
}
}
+ public static void assertClient(ClientRepresentation client, ClientRepresentation storedClient) {
+ if (client.getClientId() != null) Assert.assertEquals(client.getClientId(), storedClient.getClientId());
+ if (client.getName() != null) Assert.assertEquals(client.getName(), storedClient.getName());
+ if (client.isEnabled() != null) Assert.assertEquals(client.isEnabled(), storedClient.isEnabled());
+ if (client.isBearerOnly() != null) Assert.assertEquals(client.isBearerOnly(), storedClient.isBearerOnly());
+ if (client.isPublicClient() != null) Assert.assertEquals(client.isPublicClient(), storedClient.isPublicClient());
+ if (client.isFullScopeAllowed() != null) Assert.assertEquals(client.isFullScopeAllowed(), storedClient.isFullScopeAllowed());
+ if (client.getRootUrl() != null) Assert.assertEquals(client.getRootUrl(), storedClient.getRootUrl());
+ if (client.getAdminUrl() != null) Assert.assertEquals(client.getAdminUrl(), storedClient.getAdminUrl());
+ if (client.getBaseUrl() != null) Assert.assertEquals(client.getBaseUrl(), storedClient.getBaseUrl());
+ if (client.isSurrogateAuthRequired() != null) Assert.assertEquals(client.isSurrogateAuthRequired(), storedClient.isSurrogateAuthRequired());
+ if (client.getClientAuthenticatorType() != null) Assert.assertEquals(client.getClientAuthenticatorType(), storedClient.getClientAuthenticatorType());
+
+ if (client.getNotBefore() != null) {
+ Assert.assertEquals(client.getNotBefore(), storedClient.getNotBefore());
+ }
+ if (client.getDefaultRoles() != null) {
+ Set<String> set = new HashSet<String>();
+ for (String val : client.getDefaultRoles()) {
+ set.add(val);
+ }
+ Set<String> storedSet = new HashSet<String>();
+ for (String val : storedClient.getDefaultRoles()) {
+ storedSet.add(val);
+ }
+
+ Assert.assertEquals(set, storedSet);
+ }
+
+ List<String> redirectUris = client.getRedirectUris();
+ if (redirectUris != null) {
+ Set<String> set = new HashSet<String>();
+ for (String val : client.getRedirectUris()) {
+ set.add(val);
+ }
+ Set<String> storedSet = new HashSet<String>();
+ for (String val : storedClient.getRedirectUris()) {
+ storedSet.add(val);
+ }
+
+ Assert.assertEquals(set, storedSet);
+ }
+
+ List<String> webOrigins = client.getWebOrigins();
+ if (webOrigins != null) {
+ Set<String> set = new HashSet<String>();
+ for (String val : client.getWebOrigins()) {
+ set.add(val);
+ }
+ Set<String> storedSet = new HashSet<String>();
+ for (String val : storedClient.getWebOrigins()) {
+ storedSet.add(val);
+ }
+
+ Assert.assertEquals(set, storedSet);
+ }
+ }
+
}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/RealmTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/RealmTest.java
index 42870a6..604dcff 100644
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/RealmTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/RealmTest.java
@@ -1,6 +1,7 @@
package org.keycloak.testsuite.admin;
import org.apache.commons.io.IOUtils;
+import org.junit.Assert;
import org.junit.Test;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
@@ -8,6 +9,7 @@ import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.representations.idm.RoleRepresentation;
import org.keycloak.services.managers.RealmManager;
+import org.keycloak.testsuite.KeycloakServer;
import org.keycloak.util.JsonSerialization;
import javax.ws.rs.NotFoundException;
@@ -43,7 +45,7 @@ public class RealmTest extends AbstractClientTest {
}
@Test
- public void createRealm() {
+ public void createRealmEmpty() {
try {
RealmRepresentation rep = new RealmRepresentation();
rep.setRealm("new-realm");
@@ -63,6 +65,25 @@ public class RealmTest extends AbstractClientTest {
}
@Test
+ public void createRealm() {
+ try {
+ RealmRepresentation rep = KeycloakServer.loadJson(getClass().getResourceAsStream("/admin-test/testrealm.json"), RealmRepresentation.class);
+ keycloak.realms().create(rep);
+
+ RealmRepresentation created = keycloak.realms().realm("admin-test-1").toRepresentation();
+ assertRealm(rep, created);
+ } finally {
+ KeycloakSession session = keycloakRule.startSession();
+ RealmManager manager = new RealmManager(session);
+ RealmModel newRealm = manager.getRealmByName("admin-test-1");
+ if (newRealm != null) {
+ manager.removeRealm(newRealm);
+ }
+ keycloakRule.stopSession(session, true);
+ }
+ }
+
+ @Test
public void removeRealm() {
realm.remove();
@@ -194,4 +215,64 @@ public class RealmTest extends AbstractClientTest {
assertEquals("https://LoadBalancer-9.siroe.com:3443/federation/Consumer/metaAlias/sp", converted.getRedirectUris().get(0));
}
+ public static void assertRealm(RealmRepresentation realm, RealmRepresentation storedRealm) {
+ if (realm.getId() != null) {
+ Assert.assertEquals(realm.getId(), storedRealm.getId());
+ }
+ if (realm.getRealm() != null) {
+ Assert.assertEquals(realm.getRealm(), storedRealm.getRealm());
+ }
+ if (realm.isEnabled() != null) Assert.assertEquals(realm.isEnabled(), storedRealm.isEnabled());
+ if (realm.isBruteForceProtected() != null) Assert.assertEquals(realm.isBruteForceProtected(), storedRealm.isBruteForceProtected());
+ if (realm.getMaxFailureWaitSeconds() != null) Assert.assertEquals(realm.getMaxFailureWaitSeconds(), storedRealm.getMaxFailureWaitSeconds());
+ if (realm.getMinimumQuickLoginWaitSeconds() != null) Assert.assertEquals(realm.getMinimumQuickLoginWaitSeconds(), storedRealm.getMinimumQuickLoginWaitSeconds());
+ if (realm.getWaitIncrementSeconds() != null) Assert.assertEquals(realm.getWaitIncrementSeconds(), storedRealm.getWaitIncrementSeconds());
+ if (realm.getQuickLoginCheckMilliSeconds() != null) Assert.assertEquals(realm.getQuickLoginCheckMilliSeconds(), storedRealm.getQuickLoginCheckMilliSeconds());
+ if (realm.getMaxDeltaTimeSeconds() != null) Assert.assertEquals(realm.getMaxDeltaTimeSeconds(), storedRealm.getMaxDeltaTimeSeconds());
+ if (realm.getFailureFactor() != null) Assert.assertEquals(realm.getFailureFactor(), storedRealm.getFailureFactor());
+ if (realm.isRegistrationAllowed() != null) Assert.assertEquals(realm.isRegistrationAllowed(), storedRealm.isRegistrationAllowed());
+ if (realm.isRegistrationEmailAsUsername() != null) Assert.assertEquals(realm.isRegistrationEmailAsUsername(), storedRealm.isRegistrationEmailAsUsername());
+ if (realm.isRememberMe() != null) Assert.assertEquals(realm.isRememberMe(), storedRealm.isRememberMe());
+ if (realm.isVerifyEmail() != null) Assert.assertEquals(realm.isVerifyEmail(), storedRealm.isVerifyEmail());
+ if (realm.isResetPasswordAllowed() != null) Assert.assertEquals(realm.isResetPasswordAllowed(), storedRealm.isResetPasswordAllowed());
+ if (realm.isEditUsernameAllowed() != null) Assert.assertEquals(realm.isEditUsernameAllowed(), storedRealm.isEditUsernameAllowed());
+ if (realm.getSslRequired() != null) Assert.assertEquals(realm.getSslRequired(), storedRealm.getSslRequired());
+ if (realm.getAccessCodeLifespan() != null) Assert.assertEquals(realm.getAccessCodeLifespan(), storedRealm.getAccessCodeLifespan());
+ if (realm.getAccessCodeLifespanUserAction() != null)
+ Assert.assertEquals(realm.getAccessCodeLifespanUserAction(), storedRealm.getAccessCodeLifespanUserAction());
+ if (realm.getNotBefore() != null) Assert.assertEquals(realm.getNotBefore(), storedRealm.getNotBefore());
+ if (realm.getAccessTokenLifespan() != null) Assert.assertEquals(realm.getAccessTokenLifespan(), storedRealm.getAccessTokenLifespan());
+ if (realm.getAccessTokenLifespanForImplicitFlow() != null) Assert.assertEquals(realm.getAccessTokenLifespanForImplicitFlow(), storedRealm.getAccessTokenLifespanForImplicitFlow());
+ if (realm.getSsoSessionIdleTimeout() != null) Assert.assertEquals(realm.getSsoSessionIdleTimeout(), storedRealm.getSsoSessionIdleTimeout());
+ if (realm.getSsoSessionMaxLifespan() != null) Assert.assertEquals(realm.getSsoSessionMaxLifespan(), storedRealm.getSsoSessionMaxLifespan());
+ if (realm.getRequiredCredentials() != null) {
+ Assert.assertNotNull(storedRealm.getRequiredCredentials());
+ for (String cred : realm.getRequiredCredentials()) {
+ Assert.assertTrue(storedRealm.getRequiredCredentials().contains(cred));
+ }
+ }
+ if (realm.getLoginTheme() != null) Assert.assertEquals(realm.getLoginTheme(), storedRealm.getLoginTheme());
+ if (realm.getAccountTheme() != null) Assert.assertEquals(realm.getAccountTheme(), storedRealm.getAccountTheme());
+ if (realm.getAdminTheme() != null) Assert.assertEquals(realm.getAdminTheme(), storedRealm.getAdminTheme());
+ if (realm.getEmailTheme() != null) Assert.assertEquals(realm.getEmailTheme(), storedRealm.getEmailTheme());
+
+ if (realm.getPasswordPolicy() != null) Assert.assertEquals(realm.getPasswordPolicy(), storedRealm.getPasswordPolicy());
+
+ if (realm.getDefaultRoles() != null) {
+ Assert.assertNotNull(storedRealm.getDefaultRoles());
+ for (String role : realm.getDefaultRoles()) {
+ Assert.assertTrue(storedRealm.getDefaultRoles().contains(role));
+ }
+ }
+
+ if (realm.getSmtpServer() != null) {
+ Assert.assertEquals(realm.getSmtpServer(), storedRealm.getSmtpServer());
+ }
+
+ if (realm.getBrowserSecurityHeaders() != null) {
+ Assert.assertEquals(realm.getBrowserSecurityHeaders(), storedRealm.getBrowserSecurityHeaders());
+ }
+
+ }
+
}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/ServerInfoTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/ServerInfoTest.java
new file mode 100644
index 0000000..6c839c5
--- /dev/null
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/ServerInfoTest.java
@@ -0,0 +1,44 @@
+package org.keycloak.testsuite.admin;
+
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.Test;
+import org.keycloak.common.Version;
+import org.keycloak.representations.info.ServerInfoRepresentation;
+import org.keycloak.testsuite.OAuthClient;
+import org.keycloak.testsuite.rule.WebResource;
+import org.keycloak.testsuite.rule.WebRule;
+import org.openqa.selenium.WebDriver;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class ServerInfoTest extends AbstractClientTest {
+
+ @Rule
+ public WebRule webRule = new WebRule(this);
+
+ @WebResource
+ protected WebDriver driver;
+
+ @WebResource
+ protected OAuthClient oauth;
+
+ @Test
+ public void testServerInfo() {
+ ServerInfoRepresentation info = keycloak.serverInfo().getInfo();
+
+ Assert.assertNotNull(info);
+ Assert.assertNotNull(info.getProviders());
+ Assert.assertNotNull(info.getThemes());
+ Assert.assertNotNull(info.getEnums());
+
+ Assert.assertNotNull(info.getMemoryInfo());
+ Assert.assertNotNull(info.getSystemInfo());
+
+ Assert.assertEquals(Version.VERSION, info.getSystemInfo().getVersion());
+ Assert.assertNotNull(info.getSystemInfo().getServerTime());
+ Assert.assertNotNull(info.getSystemInfo().getUptime());
+ }
+
+}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/CacheTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/CacheTest.java
index 597e7dd..a9b907c 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/CacheTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/CacheTest.java
@@ -7,10 +7,12 @@ import org.junit.Assert;
import org.junit.ClassRule;
import org.junit.Test;
import org.keycloak.models.*;
+import org.keycloak.models.cache.infinispan.ClientAdapter;
import org.keycloak.models.cache.infinispan.RealmAdapter;
import org.keycloak.testsuite.rule.KeycloakRule;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@@ -27,10 +29,12 @@ public class CacheTest {
// load up cache
KeycloakSession session = kc.startSession();
RealmModel realm = session.realms().getRealmByName("test");
+ assertTrue(realm instanceof RealmAdapter);
ClientModel testApp = realm.getClientByClientId("test-app");
+ assertTrue(testApp instanceof ClientAdapter);
assertNotNull(testApp);
appId = testApp.getId();
- Assert.assertTrue(testApp.isEnabled());
+ assertTrue(testApp.isEnabled());
kc.stopSession(session, true);
}
{
@@ -40,16 +44,18 @@ public class CacheTest {
// KEYCLOAK-1240 - obtain the realm via session.realms().getRealms()
RealmModel realm = null;
List<RealmModel> realms = session.realms().getRealms();
+
for (RealmModel current : realms) {
+ assertTrue(current instanceof RealmAdapter);
if ("test".equals(current.getName())) {
realm = current;
break;
}
}
- Assert.assertTrue(realm instanceof RealmAdapter);
realm.setAccessCodeLifespanLogin(200);
ClientModel testApp = realm.getClientByClientId("test-app");
+
assertNotNull(testApp);
testApp.setEnabled(false);
kc.stopSession(session, true);
@@ -62,10 +68,7 @@ public class CacheTest {
ClientModel testApp = session.realms().getClientById(appId, realm);
Assert.assertFalse(testApp.isEnabled());
kc.stopSession(session, true);
-
}
-
-
}
@Test
diff --git a/testsuite/integration/src/test/resources/log4j.properties b/testsuite/integration/src/test/resources/log4j.properties
index 5bccb0e..01f6cd5 100755
--- a/testsuite/integration/src/test/resources/log4j.properties
+++ b/testsuite/integration/src/test/resources/log4j.properties
@@ -21,6 +21,9 @@ log4j.logger.org.keycloak.connections.jpa.updater.liquibase.LiquibaseJpaUpdaterP
# Enable to view infinispan initialization
# log4j.logger.org.keycloak.models.sessions.infinispan.initializer=trace
+# Enable to view cache activity
+# log4j.logger.org.keycloak.models.cache=trace
+
# Enable to view database updates
# log4j.logger.org.keycloak.connections.mongo.updater.DefaultMongoUpdaterProvider=debug
# log4j.logger.org.keycloak.connections.jpa.DefaultJpaConnectionProviderFactory=debug