diff --git a/services/src/main/java/org/keycloak/services/resources/admin/info/MemoryInfoRepresentation.java b/core/src/main/java/org/keycloak/representations/info/MemoryInfoRepresentation.java similarity index 59% rename from services/src/main/java/org/keycloak/services/resources/admin/info/MemoryInfoRepresentation.java rename to core/src/main/java/org/keycloak/representations/info/MemoryInfoRepresentation.java index 56a1110d72..7490de167a 100644 --- a/services/src/main/java/org/keycloak/services/resources/admin/info/MemoryInfoRepresentation.java +++ b/core/src/main/java/org/keycloak/representations/info/MemoryInfoRepresentation.java @@ -1,15 +1,25 @@ -package org.keycloak.services.resources.admin.info; +package org.keycloak.representations.info; public class MemoryInfoRepresentation { protected long total; + protected String totalFormated; protected long used; + protected String usedFormated; + protected long free; + protected long freePercentage; + protected String freeFormated; public static MemoryInfoRepresentation create() { MemoryInfoRepresentation rep = new MemoryInfoRepresentation(); Runtime runtime = Runtime.getRuntime(); rep.total = runtime.maxMemory(); + rep.totalFormated = formatMemory(rep.total); rep.used = runtime.totalMemory() - runtime.freeMemory(); + rep.usedFormated = formatMemory(rep.used); + rep.free = rep.total - rep.used; + rep.freeFormated = formatMemory(rep.free); + rep.freePercentage = rep.free * 100 / rep.total; return rep; } @@ -18,15 +28,15 @@ public class MemoryInfoRepresentation { } public String getTotalFormated() { - return formatMemory(getTotal()); + return totalFormated; } public long getFree() { - return getTotal() - getUsed(); + return free; } public String getFreeFormated() { - return formatMemory(getFree()); + return freeFormated; } public long getUsed() { @@ -34,14 +44,14 @@ public class MemoryInfoRepresentation { } public String getUsedFormated() { - return formatMemory(getUsed()); + return usedFormated; } public long getFreePercentage() { - return getFree() * 100 / getTotal(); + return freePercentage; } - private String formatMemory(long bytes) { + private static String formatMemory(long bytes) { if (bytes > 1024L * 1024L) { return bytes / (1024L * 1024L) + " MB"; } else if (bytes > 1024L) { diff --git a/services/src/main/java/org/keycloak/services/resources/admin/info/ProviderRepresentation.java b/core/src/main/java/org/keycloak/representations/info/ProviderRepresentation.java similarity index 86% rename from services/src/main/java/org/keycloak/services/resources/admin/info/ProviderRepresentation.java rename to core/src/main/java/org/keycloak/representations/info/ProviderRepresentation.java index ffcaeb1651..e247ff1005 100644 --- a/services/src/main/java/org/keycloak/services/resources/admin/info/ProviderRepresentation.java +++ b/core/src/main/java/org/keycloak/representations/info/ProviderRepresentation.java @@ -1,4 +1,4 @@ -package org.keycloak.services.resources.admin.info; +package org.keycloak.representations.info; import java.util.Map; diff --git a/services/src/main/java/org/keycloak/services/resources/admin/info/ServerInfoRepresentation.java b/core/src/main/java/org/keycloak/representations/info/ServerInfoRepresentation.java similarity index 98% rename from services/src/main/java/org/keycloak/services/resources/admin/info/ServerInfoRepresentation.java rename to core/src/main/java/org/keycloak/representations/info/ServerInfoRepresentation.java index 9b7f4f5bbb..01547901f1 100644 --- a/services/src/main/java/org/keycloak/services/resources/admin/info/ServerInfoRepresentation.java +++ b/core/src/main/java/org/keycloak/representations/info/ServerInfoRepresentation.java @@ -1,4 +1,4 @@ -package org.keycloak.services.resources.admin.info; +package org.keycloak.representations.info; import org.keycloak.representations.idm.ProtocolMapperRepresentation; import org.keycloak.representations.idm.ProtocolMapperTypeRepresentation; diff --git a/services/src/main/java/org/keycloak/services/resources/admin/info/SpiInfoRepresentation.java b/core/src/main/java/org/keycloak/representations/info/SpiInfoRepresentation.java similarity index 92% rename from services/src/main/java/org/keycloak/services/resources/admin/info/SpiInfoRepresentation.java rename to core/src/main/java/org/keycloak/representations/info/SpiInfoRepresentation.java index 1277f8c949..7daefb9daa 100644 --- a/services/src/main/java/org/keycloak/services/resources/admin/info/SpiInfoRepresentation.java +++ b/core/src/main/java/org/keycloak/representations/info/SpiInfoRepresentation.java @@ -1,4 +1,4 @@ -package org.keycloak.services.resources.admin.info; +package org.keycloak.representations.info; import java.util.Map; diff --git a/services/src/main/java/org/keycloak/services/resources/admin/info/SystemInfoRepresentation.java b/core/src/main/java/org/keycloak/representations/info/SystemInfoRepresentation.java similarity index 95% rename from services/src/main/java/org/keycloak/services/resources/admin/info/SystemInfoRepresentation.java rename to core/src/main/java/org/keycloak/representations/info/SystemInfoRepresentation.java index 620e25eee0..97593864c3 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/info/SystemInfoRepresentation.java +++ b/core/src/main/java/org/keycloak/representations/info/SystemInfoRepresentation.java @@ -1,7 +1,6 @@ -package org.keycloak.services.resources.admin.info; +package org.keycloak.representations.info; import org.keycloak.common.Version; -import org.keycloak.models.KeycloakSession; import java.util.Date; import java.util.Locale; @@ -27,11 +26,11 @@ public class SystemInfoRepresentation { private String userTimezone; private String userLocale; - public static SystemInfoRepresentation create(KeycloakSession session) { + public static SystemInfoRepresentation create(long serverStartupTime) { SystemInfoRepresentation rep = new SystemInfoRepresentation(); rep.version = Version.VERSION; rep.serverTime = new Date().toString(); - rep.uptimeMillis = System.currentTimeMillis() - session.getKeycloakSessionFactory().getServerStartupTimestamp(); + rep.uptimeMillis = System.currentTimeMillis() - serverStartupTime; rep.uptime = formatUptime(rep.uptimeMillis); rep.javaVersion = System.getProperty("java.version"); rep.javaVendor = System.getProperty("java.vendor"); 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 b92f65bf1f..eca236fc13 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 431a64664e..bc75fa9559 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 0000000000..6ebd642464 --- /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 Stian Thorgersen + */ +@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 1c6665aead..157842e94e 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 Bill Burke * @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 e1c356b030..0ecf8787e7 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 Bill Burke * @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 20c87251a1..2f7e61f0f3 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 4b96241fbe..5a76153793 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 realmLookup = new ConcurrentHashMap(); + private static final Logger log = Logger.getLogger(InfinispanCacheRealmProviderFactory.class); + + protected volatile InfinispanRealmCache realmCache; + + protected final ConcurrentHashMap realmLookup = new ConcurrentHashMap<>(); + + private boolean isNewInfinispan; @Override public CacheRealmProvider create(KeycloakSession session) { - Cache 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 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 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 event) { + if (event.isPre()) { + Object object = event.getValue(); + if (object != null) { + remove(object); + } + } + } + + @CacheEntryInvalidated + public void removed(CacheEntryInvalidatedEvent event) { + if (event.isPre()) { + Object object = event.getValue(); + if (object != null) { + remove(object); + } + } + } + + @CacheEntriesEvicted + public void userEvicted(CacheEntriesEvictedEvent 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 4eb0bdf8ee..ec699127c4 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 a5239fbcf5..81558012b4 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 @@ -102,6 +103,12 @@ public class InfinispanRealmCache implements RealmCache { cache.remove(id); } + @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; @@ -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 fbb36c54d4..c5e960c0e1 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 df74b536af..007daac779 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 660b1c4396..672745cb66 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/AdminAPITest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/AdminAPITest.java deleted file mode 100755 index e0471df8de..0000000000 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/AdminAPITest.java +++ /dev/null @@ -1,339 +0,0 @@ -/* - * JBoss, Home of Professional Open Source. - * Copyright 2012, Red Hat, Inc., and individual contributors - * as indicated by the @author tags. See the copyright.txt file in the - * distribution for a full listing of individual contributors. - * - * This is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This software is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this software; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA, or see the FSF site: http://www.fsf.org. - */ -package org.keycloak.testsuite.admin; - -import org.junit.Assert; -import org.junit.ClassRule; -import org.junit.Test; -import org.keycloak.Config; -import org.keycloak.common.Version; -import org.keycloak.models.ClientModel; -import org.keycloak.models.ClientSessionModel; -import org.keycloak.models.Constants; -import org.keycloak.models.KeycloakSession; -import org.keycloak.models.RealmModel; -import org.keycloak.models.UserModel; -import org.keycloak.models.UserSessionModel; -import org.keycloak.protocol.oidc.OIDCLoginProtocol; -import org.keycloak.protocol.oidc.TokenManager; -import org.keycloak.representations.AccessToken; -import org.keycloak.representations.idm.ClientRepresentation; -import org.keycloak.representations.idm.CredentialRepresentation; -import org.keycloak.representations.idm.RealmRepresentation; -import org.keycloak.services.managers.RealmManager; -import org.keycloak.services.resources.admin.AdminRoot; -import org.keycloak.testsuite.rule.AbstractKeycloakRule; -import org.keycloak.testsuite.KeycloakServer; - -import javax.ws.rs.client.Client; -import javax.ws.rs.client.ClientBuilder; -import javax.ws.rs.client.ClientRequestContext; -import javax.ws.rs.client.ClientRequestFilter; -import javax.ws.rs.client.Entity; -import javax.ws.rs.client.WebTarget; -import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.UriBuilder; -import java.io.IOException; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * Tests Undertow Adapter - * - * @author Bill Burke - */ -public class AdminAPITest { - - @ClassRule - public static AbstractKeycloakRule keycloakRule = new AbstractKeycloakRule() { - @Override - protected void configure(KeycloakSession session, RealmManager manager, RealmModel adminRealm) { - } - }; - - private static String createToken() { - KeycloakSession session = keycloakRule.startSession(); - try { - RealmManager manager = new RealmManager(session); - - RealmModel adminRealm = manager.getRealm(Config.getAdminRealm()); - ClientModel adminConsole = adminRealm.getClientByClientId(Constants.ADMIN_CLI_CLIENT_ID); - TokenManager tm = new TokenManager(); - UserModel admin = session.users().getUserByUsername("admin", adminRealm); - ClientSessionModel clientSession = session.sessions().createClientSession(adminRealm, adminConsole); - clientSession.setNote(OIDCLoginProtocol.ISSUER, "http://localhost:8081/auth/realms/master"); - UserSessionModel userSession = session.sessions().createUserSession(adminRealm, admin, "admin", null, "form", false, null, null); - AccessToken token = tm.createClientAccessToken(session, tm.getAccess(null, true, adminConsole, admin), adminRealm, adminConsole, admin, userSession, clientSession); - return tm.encodeToken(adminRealm, token); - } finally { - keycloakRule.stopSession(session, true); - } - } - - protected void testCreateRealm(RealmRepresentation rep) { - String token = createToken(); - final String authHeader = "Bearer " + token; - ClientRequestFilter authFilter = new ClientRequestFilter() { - @Override - public void filter(ClientRequestContext requestContext) throws IOException { - requestContext.getHeaders().add(HttpHeaders.AUTHORIZATION, authHeader); - } - }; - Client client = ClientBuilder.newBuilder().register(authFilter).build(); - UriBuilder authBase = UriBuilder.fromUri("http://localhost:8081/auth"); - WebTarget adminRealms = client.target(AdminRoot.realmsUrl(authBase)); - String realmName = rep.getRealm(); - WebTarget realmTarget = adminRealms.path(realmName); - - - // create with just name, enabled, and id, just like admin console - RealmRepresentation newRep = new RealmRepresentation(); - newRep.setRealm(rep.getRealm()); - newRep.setEnabled(rep.isEnabled()); - { - Response response = adminRealms.request().post(Entity.json(newRep)); - Assert.assertEquals(201, response.getStatus()); - response.close(); - } - // todo test with full import with initial create - RealmRepresentation storedRealm = realmTarget.request().get(RealmRepresentation.class); - checkRealmRep(newRep, storedRealm); - - Response updateResponse = realmTarget.request().put(Entity.json(rep)); - Assert.assertEquals(204, updateResponse.getStatus()); - updateResponse.close(); - storedRealm = realmTarget.request().get(RealmRepresentation.class); - checkRealmRep(rep, storedRealm); - - if (rep.getClients() != null) { - WebTarget applicationsTarget = realmTarget.path("applications"); - for (ClientRepresentation appRep : rep.getClients()) { - ClientRepresentation newApp = new ClientRepresentation(); - if (appRep.getId() != null) newApp.setId(appRep.getId()); - newApp.setClientId(appRep.getClientId()); - if (appRep.getClientAuthenticatorType() != null) { - newApp.setClientAuthenticatorType(appRep.getClientAuthenticatorType()); - } - if (appRep.getSecret() != null) { - newApp.setSecret(appRep.getSecret()); - } - Response appCreateResponse = applicationsTarget.request().post(Entity.json(newApp)); - Assert.assertEquals(201, appCreateResponse.getStatus()); - appCreateResponse.close(); - WebTarget appTarget = applicationsTarget.path(appRep.getClientId()); - CredentialRepresentation cred = appTarget.path("client-secret").request().get(CredentialRepresentation.class); - if (appRep.getSecret() != null) Assert.assertEquals(appRep.getSecret(), cred.getValue()); - CredentialRepresentation newCred = appTarget.path("client-secret").request().post(null, CredentialRepresentation.class); - Assert.assertNotEquals(newCred.getValue(), cred.getValue()); - - Response appUpdateResponse = appTarget.request().put(Entity.json(appRep)); - Assert.assertEquals(204, appUpdateResponse.getStatus()); - appUpdateResponse.close(); - - - ClientRepresentation storedApp = appTarget.request().get(ClientRepresentation.class); - - checkAppUpdate(appRep, storedApp); - - } - } - - // delete realm - { - Response response = adminRealms.path(realmName).request().delete(); - Assert.assertEquals(204, response.getStatus()); - response.close(); - - } - client.close(); - } - - protected void checkAppUpdate(ClientRepresentation appRep, ClientRepresentation storedApp) { - if (appRep.getClientId() != null) Assert.assertEquals(appRep.getClientId(), storedApp.getClientId()); - if (appRep.getName() != null) Assert.assertEquals(appRep.getName(), storedApp.getName()); - if (appRep.isEnabled() != null) Assert.assertEquals(appRep.isEnabled(), storedApp.isEnabled()); - if (appRep.isBearerOnly() != null) Assert.assertEquals(appRep.isBearerOnly(), storedApp.isBearerOnly()); - if (appRep.isPublicClient() != null) Assert.assertEquals(appRep.isPublicClient(), storedApp.isPublicClient()); - if (appRep.isFullScopeAllowed() != null) Assert.assertEquals(appRep.isFullScopeAllowed(), storedApp.isFullScopeAllowed()); - if (appRep.getRootUrl() != null) Assert.assertEquals(appRep.getRootUrl(), storedApp.getRootUrl()); - if (appRep.getAdminUrl() != null) Assert.assertEquals(appRep.getAdminUrl(), storedApp.getAdminUrl()); - if (appRep.getBaseUrl() != null) Assert.assertEquals(appRep.getBaseUrl(), storedApp.getBaseUrl()); - if (appRep.isSurrogateAuthRequired() != null) Assert.assertEquals(appRep.isSurrogateAuthRequired(), storedApp.isSurrogateAuthRequired()); - if (appRep.getClientAuthenticatorType() != null) Assert.assertEquals(appRep.getClientAuthenticatorType(), storedApp.getClientAuthenticatorType()); - - if (appRep.getNotBefore() != null) { - Assert.assertEquals(appRep.getNotBefore(), storedApp.getNotBefore()); - } - if (appRep.getDefaultRoles() != null) { - Set set = new HashSet(); - for (String val : appRep.getDefaultRoles()) { - set.add(val); - } - Set storedSet = new HashSet(); - for (String val : storedApp.getDefaultRoles()) { - storedSet.add(val); - } - - Assert.assertEquals(set, storedSet); - } - - List redirectUris = appRep.getRedirectUris(); - if (redirectUris != null) { - Set set = new HashSet(); - for (String val : appRep.getRedirectUris()) { - set.add(val); - } - Set storedSet = new HashSet(); - for (String val : storedApp.getRedirectUris()) { - storedSet.add(val); - } - - Assert.assertEquals(set, storedSet); - } - - List webOrigins = appRep.getWebOrigins(); - if (webOrigins != null) { - Set set = new HashSet(); - for (String val : appRep.getWebOrigins()) { - set.add(val); - } - Set storedSet = new HashSet(); - for (String val : storedApp.getWebOrigins()) { - storedSet.add(val); - } - - Assert.assertEquals(set, storedSet); - } - } - - protected void checkRealmRep(RealmRepresentation rep, RealmRepresentation storedRealm) { - if (rep.getId() != null) { - Assert.assertEquals(rep.getId(), storedRealm.getId()); - } - if (rep.getRealm() != null) { - Assert.assertEquals(rep.getRealm(), storedRealm.getRealm()); - } - if (rep.isEnabled() != null) Assert.assertEquals(rep.isEnabled(), storedRealm.isEnabled()); - if (rep.isBruteForceProtected() != null) Assert.assertEquals(rep.isBruteForceProtected(), storedRealm.isBruteForceProtected()); - if (rep.getMaxFailureWaitSeconds() != null) Assert.assertEquals(rep.getMaxFailureWaitSeconds(), storedRealm.getMaxFailureWaitSeconds()); - if (rep.getMinimumQuickLoginWaitSeconds() != null) Assert.assertEquals(rep.getMinimumQuickLoginWaitSeconds(), storedRealm.getMinimumQuickLoginWaitSeconds()); - if (rep.getWaitIncrementSeconds() != null) Assert.assertEquals(rep.getWaitIncrementSeconds(), storedRealm.getWaitIncrementSeconds()); - if (rep.getQuickLoginCheckMilliSeconds() != null) Assert.assertEquals(rep.getQuickLoginCheckMilliSeconds(), storedRealm.getQuickLoginCheckMilliSeconds()); - if (rep.getMaxDeltaTimeSeconds() != null) Assert.assertEquals(rep.getMaxDeltaTimeSeconds(), storedRealm.getMaxDeltaTimeSeconds()); - if (rep.getFailureFactor() != null) Assert.assertEquals(rep.getFailureFactor(), storedRealm.getFailureFactor()); - if (rep.isRegistrationAllowed() != null) Assert.assertEquals(rep.isRegistrationAllowed(), storedRealm.isRegistrationAllowed()); - if (rep.isRegistrationEmailAsUsername() != null) Assert.assertEquals(rep.isRegistrationEmailAsUsername(), storedRealm.isRegistrationEmailAsUsername()); - if (rep.isRememberMe() != null) Assert.assertEquals(rep.isRememberMe(), storedRealm.isRememberMe()); - if (rep.isVerifyEmail() != null) Assert.assertEquals(rep.isVerifyEmail(), storedRealm.isVerifyEmail()); - if (rep.isResetPasswordAllowed() != null) Assert.assertEquals(rep.isResetPasswordAllowed(), storedRealm.isResetPasswordAllowed()); - if (rep.isEditUsernameAllowed() != null) Assert.assertEquals(rep.isEditUsernameAllowed(), storedRealm.isEditUsernameAllowed()); - if (rep.getSslRequired() != null) Assert.assertEquals(rep.getSslRequired(), storedRealm.getSslRequired()); - if (rep.getAccessCodeLifespan() != null) Assert.assertEquals(rep.getAccessCodeLifespan(), storedRealm.getAccessCodeLifespan()); - if (rep.getAccessCodeLifespanUserAction() != null) - Assert.assertEquals(rep.getAccessCodeLifespanUserAction(), storedRealm.getAccessCodeLifespanUserAction()); - if (rep.getNotBefore() != null) Assert.assertEquals(rep.getNotBefore(), storedRealm.getNotBefore()); - if (rep.getAccessTokenLifespan() != null) Assert.assertEquals(rep.getAccessTokenLifespan(), storedRealm.getAccessTokenLifespan()); - if (rep.getAccessTokenLifespanForImplicitFlow() != null) Assert.assertEquals(rep.getAccessTokenLifespanForImplicitFlow(), storedRealm.getAccessTokenLifespanForImplicitFlow()); - if (rep.getSsoSessionIdleTimeout() != null) Assert.assertEquals(rep.getSsoSessionIdleTimeout(), storedRealm.getSsoSessionIdleTimeout()); - if (rep.getSsoSessionMaxLifespan() != null) Assert.assertEquals(rep.getSsoSessionMaxLifespan(), storedRealm.getSsoSessionMaxLifespan()); - if (rep.getRequiredCredentials() != null) { - Assert.assertNotNull(storedRealm.getRequiredCredentials()); - for (String cred : rep.getRequiredCredentials()) { - Assert.assertTrue(storedRealm.getRequiredCredentials().contains(cred)); - } - } - if (rep.getLoginTheme() != null) Assert.assertEquals(rep.getLoginTheme(), storedRealm.getLoginTheme()); - if (rep.getAccountTheme() != null) Assert.assertEquals(rep.getAccountTheme(), storedRealm.getAccountTheme()); - if (rep.getAdminTheme() != null) Assert.assertEquals(rep.getAdminTheme(), storedRealm.getAdminTheme()); - if (rep.getEmailTheme() != null) Assert.assertEquals(rep.getEmailTheme(), storedRealm.getEmailTheme()); - - if (rep.getPasswordPolicy() != null) Assert.assertEquals(rep.getPasswordPolicy(), storedRealm.getPasswordPolicy()); - - if (rep.getDefaultRoles() != null) { - Assert.assertNotNull(storedRealm.getDefaultRoles()); - for (String role : rep.getDefaultRoles()) { - Assert.assertTrue(storedRealm.getDefaultRoles().contains(role)); - } - } - - if (rep.getSmtpServer() != null) { - Assert.assertEquals(rep.getSmtpServer(), storedRealm.getSmtpServer()); - } - - if (rep.getBrowserSecurityHeaders() != null) { - Assert.assertEquals(rep.getBrowserSecurityHeaders(), storedRealm.getBrowserSecurityHeaders()); - } - - } - - protected void testCreateRealm(String path) { - RealmRepresentation rep = KeycloakServer.loadJson(getClass().getResourceAsStream(path), RealmRepresentation.class); - Assert.assertNotNull(rep); - testCreateRealm(rep); - } - - @Test - public void testAdminApi() { - RealmRepresentation empty = new RealmRepresentation(); - empty.setEnabled(true); - empty.setRealm("empty"); - testCreateRealm(empty); - testCreateRealm("/admin-test/testrealm.json"); - } - - @Test - public void testServerInfo() { - String token = createToken(); - final String authHeader = "Bearer " + token; - ClientRequestFilter authFilter = new ClientRequestFilter() { - @Override - public void filter(ClientRequestContext requestContext) throws IOException { - requestContext.getHeaders().add(HttpHeaders.AUTHORIZATION, authHeader); - } - }; - Client client = ClientBuilder.newBuilder().register(authFilter).build(); - UriBuilder authBase = UriBuilder.fromUri("http://localhost:8081/auth"); - WebTarget target = client.target(AdminRoot.adminBaseUrl(authBase).path("serverinfo")); - - Map response = target.request().accept("application/json").get(Map.class); - - - System.out.println(response.keySet().toString()); - - Assert.assertNotNull(response); - Assert.assertNotNull(response.get("providers")); - Assert.assertNotNull(response.get("themes")); - Assert.assertNotNull(response.get("enums")); - - Assert.assertNotNull(response.get("memoryInfo")); - Assert.assertNotNull(response.get("systemInfo")); - - Map systemInfo = (Map) response.get("systemInfo"); - Assert.assertEquals(Version.VERSION, systemInfo.get("version")); - Assert.assertNotNull(systemInfo.get("serverTime")); - Assert.assertNotNull(systemInfo.get("uptime")); - } - -} 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 dd575b1d64..31f88bcf71 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 set = new HashSet(); + for (String val : client.getDefaultRoles()) { + set.add(val); + } + Set storedSet = new HashSet(); + for (String val : storedClient.getDefaultRoles()) { + storedSet.add(val); + } + + Assert.assertEquals(set, storedSet); + } + + List redirectUris = client.getRedirectUris(); + if (redirectUris != null) { + Set set = new HashSet(); + for (String val : client.getRedirectUris()) { + set.add(val); + } + Set storedSet = new HashSet(); + for (String val : storedClient.getRedirectUris()) { + storedSet.add(val); + } + + Assert.assertEquals(set, storedSet); + } + + List webOrigins = client.getWebOrigins(); + if (webOrigins != null) { + Set set = new HashSet(); + for (String val : client.getWebOrigins()) { + set.add(val); + } + Set storedSet = new HashSet(); + 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 42870a6642..604dcffca4 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"); @@ -62,6 +64,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 0000000000..6c839c5997 --- /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 Stian Thorgersen + */ +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 597e7dd5d4..a9b907c612 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 Bill Burke @@ -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 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 5bccb0e624..01f6cd503e 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