keycloak-memoizeit
Changes
common/pom.xml 5(+5 -0)
common/src/main/java/org/keycloak/common/Profile.java 201(+132 -69)
distribution/adapters/as7-eap6-adapter/as7-modules/src/main/resources/modules/org/keycloak/keycloak-common/main/module.xml 1(+1 -0)
distribution/adapters/wf8-adapter/wf8-modules/src/main/resources/modules/org/keycloak/keycloak-common/main/module.xml 1(+1 -0)
distribution/feature-packs/adapter-feature-pack/src/main/resources/modules/system/add-ons/keycloak/org/keycloak/keycloak-common/main/module.xml 1(+1 -0)
distribution/feature-packs/server-feature-pack/src/main/resources/modules/system/layers/keycloak/org/keycloak/keycloak-common/main/module.xml 1(+1 -0)
distribution/saml-adapters/as7-eap6-adapter/as7-modules/src/main/resources/modules/org/keycloak/keycloak-common/main/module.xml 1(+1 -0)
distribution/saml-adapters/wildfly-adapter/wildfly-modules/src/main/resources/modules/org/keycloak/keycloak-common/main/module.xml 1(+1 -0)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/AccountRestServiceTest.java 12(+6 -6)
Details
common/pom.xml 5(+5 -0)
diff --git a/common/pom.xml b/common/pom.xml
index 4ec3062..9df7512 100755
--- a/common/pom.xml
+++ b/common/pom.xml
@@ -51,6 +51,11 @@
<artifactId>bcpkix-jdk15on</artifactId>
</dependency>
<dependency>
+ <groupId>org.jboss.logging</groupId>
+ <artifactId>jboss-logging</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
common/src/main/java/org/keycloak/common/Profile.java 201(+132 -69)
diff --git a/common/src/main/java/org/keycloak/common/Profile.java b/common/src/main/java/org/keycloak/common/Profile.java
index 04d4f0b..e7a2a23 100755
--- a/common/src/main/java/org/keycloak/common/Profile.java
+++ b/common/src/main/java/org/keycloak/common/Profile.java
@@ -17,12 +17,12 @@
package org.keycloak.common;
+import org.jboss.logging.Logger;
+
import java.io.File;
import java.io.FileInputStream;
-import java.util.Arrays;
-import java.util.Collections;
+import java.io.IOException;
import java.util.HashSet;
-import java.util.List;
import java.util.Properties;
import java.util.Set;
@@ -32,95 +32,101 @@ import java.util.Set;
*/
public class Profile {
- public enum Feature {
- ACCOUNT2,
- ADMIN_FINE_GRAINED_AUTHZ,
- DOCKER,
- IMPERSONATION,
- OPENSHIFT_INTEGRATION,
- SCRIPTS,
- TOKEN_EXCHANGE
- }
+ private static final Logger logger = Logger.getLogger(Profile.class);
- private enum ProductValue {
- KEYCLOAK(),
- RHSSO(Feature.ACCOUNT2);
+ public enum Type {
+ DEFAULT,
+ DISABLED_BY_DEFAULT,
+ PREVIEW,
+ EXPERIMENTAL
+ }
- private List<Feature> excluded;
+ public enum Feature {
+ ACCOUNT2(Type.EXPERIMENTAL),
+ ACCOUNT_API(Type.PREVIEW),
+ ADMIN_FINE_GRAINED_AUTHZ(Type.PREVIEW),
+ DOCKER(Type.DISABLED_BY_DEFAULT),
+ IMPERSONATION(Type.DEFAULT),
+ OPENSHIFT_INTEGRATION(Type.DEFAULT),
+ SCRIPTS(Type.PREVIEW),
+ TOKEN_EXCHANGE(Type.PREVIEW);
+
+ private Type type;
+
+ Feature(Type type) {
+ this.type = type;
+ }
- ProductValue(Feature... excluded) {
- this.excluded = Arrays.asList(excluded);
+ public Type getType() {
+ return type;
}
}
- private enum ProfileValue {
- PRODUCT(Feature.ADMIN_FINE_GRAINED_AUTHZ, Feature.SCRIPTS, Feature.DOCKER, Feature.ACCOUNT2, Feature.TOKEN_EXCHANGE),
- PREVIEW(Feature.ACCOUNT2),
- COMMUNITY(Feature.DOCKER, Feature.ACCOUNT2);
-
- private List<Feature> disabled;
+ private enum ProductValue {
+ KEYCLOAK,
+ RHSSO
+ }
- ProfileValue(Feature... disabled) {
- this.disabled = Arrays.asList(disabled);
- }
+ private enum ProfileValue {
+ COMMUNITY,
+ PRODUCT,
+ PREVIEW
}
- private static final Profile CURRENT = new Profile();
+ private static Profile CURRENT = new Profile();
private final ProductValue product;
private final ProfileValue profile;
private final Set<Feature> disabledFeatures = new HashSet<>();
+ private final Set<Feature> previewFeatures = new HashSet<>();
+ private final Set<Feature> experimentalFeatures = new HashSet<>();
private Profile() {
- product = "rh-sso".equals(Version.NAME) ? ProductValue.RHSSO : ProductValue.KEYCLOAK;
+ Config config = new Config();
- try {
- Properties props = new Properties();
-
- String jbossServerConfigDir = System.getProperty("jboss.server.config.dir");
- if (jbossServerConfigDir != null) {
- File file = new File(jbossServerConfigDir, "profile.properties");
- if (file.isFile()) {
- props.load(new FileInputStream(file));
- }
- }
-
- if (System.getProperties().containsKey("keycloak.profile")) {
- props.setProperty("profile", System.getProperty("keycloak.profile"));
- }
-
- for (String k : System.getProperties().stringPropertyNames()) {
- if (k.startsWith("keycloak.profile.feature.")) {
- props.put(k.replace("keycloak.profile.feature.", "feature."), System.getProperty(k));
- }
- }
-
- if (props.containsKey("profile")) {
- profile = ProfileValue.valueOf(props.getProperty("profile").toUpperCase());
- } else {
- profile = ProfileValue.valueOf(Version.DEFAULT_PROFILE.toUpperCase());
- }
+ product = "rh-sso".equals(Version.NAME) ? ProductValue.RHSSO : ProductValue.KEYCLOAK;
+ profile = ProfileValue.valueOf(config.getProfile().toUpperCase());
- disabledFeatures.addAll(profile.disabled);
- disabledFeatures.removeAll(product.excluded);
+ for (Feature f : Feature.values()) {
+ Boolean enabled = config.getConfig(f);
- for (String k : props.stringPropertyNames()) {
- if (k.startsWith("feature.")) {
- Feature f = Feature.valueOf(k.replace("feature.", "").toUpperCase());
- if (props.get(k).equals("enabled")) {
- disabledFeatures.remove(f);
- } else if (props.get(k).equals("disabled")) {
+ switch (f.getType()) {
+ case DEFAULT:
+ if (enabled != null && !enabled) {
disabledFeatures.add(f);
}
- }
+ break;
+ case DISABLED_BY_DEFAULT:
+ if (enabled == null || !enabled) {
+ disabledFeatures.add(f);
+ }
+ break;
+ case PREVIEW:
+ previewFeatures.add(f);
+ if (enabled == null || !enabled) {
+ disabledFeatures.add(f);
+ } else {
+ logger.info("Preview feature enabled: " + f.name().toLowerCase());
+ }
+ break;
+ case EXPERIMENTAL:
+ experimentalFeatures.add(f);
+ if (enabled == null || !enabled) {
+ disabledFeatures.add(f);
+ } else {
+ logger.warn("Experimental feature enabled: " + f.name().toLowerCase());
+ }
+ break;
}
- } catch (Exception e) {
- throw new RuntimeException(e);
}
}
+ public static void init() {
+ CURRENT = new Profile();
+ }
+
public static String getName() {
return CURRENT.profile.name().toLowerCase();
}
@@ -129,11 +135,68 @@ public class Profile {
return CURRENT.disabledFeatures;
}
+ public static Set<Feature> getPreviewFeatures() {
+ return CURRENT.previewFeatures;
+ }
+
+ public static Set<Feature> getExperimentalFeatures() {
+ return CURRENT.experimentalFeatures;
+ }
+
public static boolean isFeatureEnabled(Feature feature) {
- if (CURRENT.product.excluded.contains(feature)) {
- return false;
- }
return !CURRENT.disabledFeatures.contains(feature);
}
+ private class Config {
+
+ private Properties properties;
+
+ public Config() {
+ properties = new Properties();
+
+ try {
+ String jbossServerConfigDir = System.getProperty("jboss.server.config.dir");
+ if (jbossServerConfigDir != null) {
+ File file = new File(jbossServerConfigDir, "profile.properties");
+ if (file.isFile()) {
+ properties.load(new FileInputStream(file));
+ }
+ }
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public String getProfile() {
+ String profile = System.getProperty("keycloak.profile");
+ if (profile != null) {
+ return profile;
+ }
+
+ profile = properties.getProperty("profile");
+ if (profile != null) {
+ return profile;
+ }
+
+ return Version.DEFAULT_PROFILE;
+ }
+
+ public Boolean getConfig(Feature feature) {
+ String config = System.getProperty("keycloak.profile.feature." + feature.name().toLowerCase());
+ if (config == null) {
+ config = properties.getProperty("feature." + feature.name().toLowerCase());
+ }
+
+ if (config == null) {
+ return null;
+ } else if (config.equals("enabled")) {
+ return Boolean.TRUE;
+ } else if (config.equals("disabled")) {
+ return Boolean.FALSE;
+ } else {
+ throw new RuntimeException("Invalid value for feature " + config);
+ }
+ }
+ }
+
}
diff --git a/common/src/test/java/org/keycloak/common/ProfileTest.java b/common/src/test/java/org/keycloak/common/ProfileTest.java
new file mode 100644
index 0000000..827e08e
--- /dev/null
+++ b/common/src/test/java/org/keycloak/common/ProfileTest.java
@@ -0,0 +1,97 @@
+package org.keycloak.common;
+
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.Properties;
+import java.util.Set;
+
+public class ProfileTest {
+
+ @Rule
+ public TemporaryFolder temporaryFolder = new TemporaryFolder();
+
+ @Test
+ public void checkDefaults() {
+ Assert.assertEquals("community", Profile.getName());
+ assertEquals(Profile.getDisabledFeatures(), Profile.Feature.ACCOUNT2, Profile.Feature.ACCOUNT_API, Profile.Feature.ADMIN_FINE_GRAINED_AUTHZ, Profile.Feature.DOCKER, Profile.Feature.SCRIPTS, Profile.Feature.TOKEN_EXCHANGE);
+ assertEquals(Profile.getPreviewFeatures(), Profile.Feature.ACCOUNT_API, Profile.Feature.ADMIN_FINE_GRAINED_AUTHZ, Profile.Feature.SCRIPTS, Profile.Feature.TOKEN_EXCHANGE);
+ assertEquals(Profile.getExperimentalFeatures(), Profile.Feature.ACCOUNT2);
+ }
+
+ @Test
+ public void configWithSystemProperties() {
+ Assert.assertEquals("community", Profile.getName());
+ Assert.assertFalse(Profile.isFeatureEnabled(Profile.Feature.DOCKER));
+ Assert.assertTrue(Profile.isFeatureEnabled(Profile.Feature.IMPERSONATION));
+
+ System.setProperty("keycloak.profile", "preview");
+ System.setProperty("keycloak.profile.feature.docker", "enabled");
+ System.setProperty("keycloak.profile.feature.impersonation", "disabled");
+
+ Profile.init();
+
+ Assert.assertEquals("preview", Profile.getName());
+ Assert.assertTrue(Profile.isFeatureEnabled(Profile.Feature.DOCKER));
+ Assert.assertFalse(Profile.isFeatureEnabled(Profile.Feature.IMPERSONATION));
+
+ System.getProperties().remove("keycloak.profile");
+ System.getProperties().remove("keycloak.profile.feature.docker");
+ System.getProperties().remove("keycloak.profile.feature.impersonation");
+
+ Profile.init();
+ }
+
+ @Test
+ public void configWithPropertiesFile() throws IOException {
+ Assert.assertEquals("community", Profile.getName());
+ Assert.assertFalse(Profile.isFeatureEnabled(Profile.Feature.DOCKER));
+ Assert.assertTrue(Profile.isFeatureEnabled(Profile.Feature.IMPERSONATION));
+
+ File d = temporaryFolder.newFolder();
+ File f = new File(d, "profile.properties");
+
+ Properties p = new Properties();
+ p.setProperty("profile", "preview");
+ p.setProperty("feature.docker", "enabled");
+ p.setProperty("feature.impersonation", "disabled");
+ PrintWriter pw = new PrintWriter(f);
+ p.list(pw);
+ pw.close();
+
+ System.setProperty("jboss.server.config.dir", d.getAbsolutePath());
+
+ Profile.init();
+
+ Assert.assertEquals("preview", Profile.getName());
+ Assert.assertTrue(Profile.isFeatureEnabled(Profile.Feature.DOCKER));
+ Assert.assertFalse(Profile.isFeatureEnabled(Profile.Feature.IMPERSONATION));
+
+ System.getProperties().remove("jboss.server.config.dir");
+
+ Profile.init();
+ }
+
+ public static void assertEquals(Set<Profile.Feature> actual, Profile.Feature... expected) {
+ Profile.Feature[] a = actual.toArray(new Profile.Feature[actual.size()]);
+ Arrays.sort(a, new FeatureComparator());
+ Arrays.sort(expected, new FeatureComparator());
+ Assert.assertArrayEquals(a, expected);
+ }
+
+ private static class FeatureComparator implements Comparator<Profile.Feature> {
+ @Override
+ public int compare(Profile.Feature o1, Profile.Feature o2) {
+ return o1.name().compareTo(o2.name());
+ }
+ }
+
+}
diff --git a/core/src/main/java/org/keycloak/representations/info/ProfileInfoRepresentation.java b/core/src/main/java/org/keycloak/representations/info/ProfileInfoRepresentation.java
index c0cbea8..52481bc 100644
--- a/core/src/main/java/org/keycloak/representations/info/ProfileInfoRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/info/ProfileInfoRepresentation.java
@@ -21,6 +21,7 @@ import org.keycloak.common.Profile;
import java.util.LinkedList;
import java.util.List;
+import java.util.Set;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
@@ -29,15 +30,16 @@ public class ProfileInfoRepresentation {
private String name;
private List<String> disabledFeatures;
+ private List<String> previewFeatures;
+ private List<String> experimentalFeatures;
public static ProfileInfoRepresentation create() {
ProfileInfoRepresentation info = new ProfileInfoRepresentation();
info.name = Profile.getName();
- info.disabledFeatures = new LinkedList<>();
- for (Profile.Feature f : Profile.getDisabledFeatures()) {
- info.disabledFeatures.add(f.name());
- }
+ info.disabledFeatures = names(Profile.getDisabledFeatures());
+ info.previewFeatures = names(Profile.getPreviewFeatures());
+ info.experimentalFeatures = names(Profile.getExperimentalFeatures());
return info;
}
@@ -50,4 +52,20 @@ public class ProfileInfoRepresentation {
return disabledFeatures;
}
+ public List<String> getPreviewFeatures() {
+ return previewFeatures;
+ }
+
+ public List<String> getExperimentalFeatures() {
+ return experimentalFeatures;
+ }
+
+ private static List<String> names(Set<Profile.Feature> featureSet) {
+ List<String> l = new LinkedList();
+ for (Profile.Feature f : featureSet) {
+ l.add(f.name());
+ }
+ return l;
+ }
+
}
diff --git a/distribution/adapters/as7-eap6-adapter/as7-modules/src/main/resources/modules/org/keycloak/keycloak-common/main/module.xml b/distribution/adapters/as7-eap6-adapter/as7-modules/src/main/resources/modules/org/keycloak/keycloak-common/main/module.xml
index 4afb80d..695dc1a 100755
--- a/distribution/adapters/as7-eap6-adapter/as7-modules/src/main/resources/modules/org/keycloak/keycloak-common/main/module.xml
+++ b/distribution/adapters/as7-eap6-adapter/as7-modules/src/main/resources/modules/org/keycloak/keycloak-common/main/module.xml
@@ -27,6 +27,7 @@
<module name="org.bouncycastle" />
<module name="javax.api"/>
<module name="javax.activation.api"/>
+ <module name="org.jboss.logging"/>
<module name="sun.jdk" optional="true" />
</dependencies>
diff --git a/distribution/adapters/wf8-adapter/wf8-modules/src/main/resources/modules/org/keycloak/keycloak-common/main/module.xml b/distribution/adapters/wf8-adapter/wf8-modules/src/main/resources/modules/org/keycloak/keycloak-common/main/module.xml
index 4afb80d..695dc1a 100755
--- a/distribution/adapters/wf8-adapter/wf8-modules/src/main/resources/modules/org/keycloak/keycloak-common/main/module.xml
+++ b/distribution/adapters/wf8-adapter/wf8-modules/src/main/resources/modules/org/keycloak/keycloak-common/main/module.xml
@@ -27,6 +27,7 @@
<module name="org.bouncycastle" />
<module name="javax.api"/>
<module name="javax.activation.api"/>
+ <module name="org.jboss.logging"/>
<module name="sun.jdk" optional="true" />
</dependencies>
diff --git a/distribution/feature-packs/adapter-feature-pack/src/main/resources/modules/system/add-ons/keycloak/org/keycloak/keycloak-common/main/module.xml b/distribution/feature-packs/adapter-feature-pack/src/main/resources/modules/system/add-ons/keycloak/org/keycloak/keycloak-common/main/module.xml
index 81578ae..7e96423 100755
--- a/distribution/feature-packs/adapter-feature-pack/src/main/resources/modules/system/add-ons/keycloak/org/keycloak/keycloak-common/main/module.xml
+++ b/distribution/feature-packs/adapter-feature-pack/src/main/resources/modules/system/add-ons/keycloak/org/keycloak/keycloak-common/main/module.xml
@@ -27,6 +27,7 @@
<module name="org.bouncycastle" />
<module name="javax.api"/>
<module name="javax.activation.api"/>
+ <module name="org.jboss.logging"/>
<module name="sun.jdk" optional="true" />
</dependencies>
diff --git a/distribution/feature-packs/server-feature-pack/src/main/resources/modules/system/layers/keycloak/org/keycloak/keycloak-common/main/module.xml b/distribution/feature-packs/server-feature-pack/src/main/resources/modules/system/layers/keycloak/org/keycloak/keycloak-common/main/module.xml
index 7b024b1..ee73fde 100755
--- a/distribution/feature-packs/server-feature-pack/src/main/resources/modules/system/layers/keycloak/org/keycloak/keycloak-common/main/module.xml
+++ b/distribution/feature-packs/server-feature-pack/src/main/resources/modules/system/layers/keycloak/org/keycloak/keycloak-common/main/module.xml
@@ -24,6 +24,7 @@
<module name="org.bouncycastle" />
<module name="javax.api"/>
<module name="javax.activation.api"/>
+ <module name="org.jboss.logging"/>
<module name="sun.jdk" optional="true" />
</dependencies>
</module>
diff --git a/distribution/saml-adapters/as7-eap6-adapter/as7-modules/src/main/resources/modules/org/keycloak/keycloak-common/main/module.xml b/distribution/saml-adapters/as7-eap6-adapter/as7-modules/src/main/resources/modules/org/keycloak/keycloak-common/main/module.xml
index 4afb80d..695dc1a 100755
--- a/distribution/saml-adapters/as7-eap6-adapter/as7-modules/src/main/resources/modules/org/keycloak/keycloak-common/main/module.xml
+++ b/distribution/saml-adapters/as7-eap6-adapter/as7-modules/src/main/resources/modules/org/keycloak/keycloak-common/main/module.xml
@@ -27,6 +27,7 @@
<module name="org.bouncycastle" />
<module name="javax.api"/>
<module name="javax.activation.api"/>
+ <module name="org.jboss.logging"/>
<module name="sun.jdk" optional="true" />
</dependencies>
diff --git a/distribution/saml-adapters/wildfly-adapter/wildfly-modules/src/main/resources/modules/org/keycloak/keycloak-common/main/module.xml b/distribution/saml-adapters/wildfly-adapter/wildfly-modules/src/main/resources/modules/org/keycloak/keycloak-common/main/module.xml
index 4afb80d..695dc1a 100755
--- a/distribution/saml-adapters/wildfly-adapter/wildfly-modules/src/main/resources/modules/org/keycloak/keycloak-common/main/module.xml
+++ b/distribution/saml-adapters/wildfly-adapter/wildfly-modules/src/main/resources/modules/org/keycloak/keycloak-common/main/module.xml
@@ -27,6 +27,7 @@
<module name="org.bouncycastle" />
<module name="javax.api"/>
<module name="javax.activation.api"/>
+ <module name="org.jboss.logging"/>
<module name="sun.jdk" optional="true" />
</dependencies>
diff --git a/services/src/main/java/org/keycloak/services/resources/account/AccountRestService.java b/services/src/main/java/org/keycloak/services/resources/account/AccountRestService.java
index 0a39dd4..72fe538 100755
--- a/services/src/main/java/org/keycloak/services/resources/account/AccountRestService.java
+++ b/services/src/main/java/org/keycloak/services/resources/account/AccountRestService.java
@@ -206,7 +206,7 @@ public class AccountRestService {
@Produces(MediaType.APPLICATION_JSON)
@NoCache
public Response sessions() {
- checkAccount2Enabled();
+ checkAccountApiEnabled();
List<SessionRepresentation> reps = new LinkedList<>();
List<UserSessionModel> sessions = session.sessions().getUserSessions(realm, user);
@@ -244,7 +244,7 @@ public class AccountRestService {
@Produces(MediaType.APPLICATION_JSON)
@NoCache
public Response sessionsLogout(@QueryParam("current") boolean removeCurrent) {
- checkAccount2Enabled();
+ checkAccountApiEnabled();
UserSessionModel userSession = auth.getSession();
List<UserSessionModel> userSessions = session.sessions().getUserSessions(realm, user);
@@ -268,7 +268,7 @@ public class AccountRestService {
@Produces(MediaType.APPLICATION_JSON)
@NoCache
public Response sessionLogout(@QueryParam("id") String id) {
- checkAccount2Enabled();
+ checkAccountApiEnabled();
UserSessionModel userSession = session.sessions().getUserSession(realm, id);
if (userSession != null && userSession.getUser().equals(user)) {
AuthenticationManager.backchannelLogout(session, userSession, true);
@@ -278,7 +278,7 @@ public class AccountRestService {
@Path("/credentials")
public AccountCredentialResource credentials() {
- checkAccount2Enabled();
+ checkAccountApiEnabled();
return new AccountCredentialResource(session, event, user);
}
@@ -286,8 +286,8 @@ public class AccountRestService {
// TODO Applications
// TODO Logs
- private static void checkAccount2Enabled() {
- if (!Profile.isFeatureEnabled(Profile.Feature.ACCOUNT2)) {
+ private static void checkAccountApiEnabled() {
+ if (!Profile.isFeatureEnabled(Profile.Feature.ACCOUNT_API)) {
throw new NotFoundException();
}
}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/AccountRestServiceTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/AccountRestServiceTest.java
index b24ec81..0cbda1b 100755
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/AccountRestServiceTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/AccountRestServiceTest.java
@@ -44,7 +44,7 @@ import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.junit.Assert.*;
import org.keycloak.services.messages.Messages;
-import static org.keycloak.common.Profile.Feature.ACCOUNT2;
+import static org.keycloak.common.Profile.Feature.ACCOUNT_API;
import static org.keycloak.testsuite.ProfileAssume.assumeFeatureEnabled;
/**
@@ -234,7 +234,7 @@ public class AccountRestServiceTest extends AbstractTestRealmKeycloakTest {
@Test
public void testGetSessions() throws IOException {
- assumeFeatureEnabled(ACCOUNT2);
+ assumeFeatureEnabled(ACCOUNT_API);
List<SessionRepresentation> sessions = SimpleHttp.doGet(getAccountUrl("sessions"), client).auth(tokenUtil.getToken()).asJson(new TypeReference<List<SessionRepresentation>>() {});
@@ -243,14 +243,14 @@ public class AccountRestServiceTest extends AbstractTestRealmKeycloakTest {
@Test
public void testGetPasswordDetails() throws IOException {
- assumeFeatureEnabled(ACCOUNT2);
+ assumeFeatureEnabled(ACCOUNT_API);
getPasswordDetails();
}
@Test
public void testPostPasswordUpdate() throws IOException {
- assumeFeatureEnabled(ACCOUNT2);
+ assumeFeatureEnabled(ACCOUNT_API);
//Get the time of lastUpdate
AccountCredentialResource.PasswordDetails initialDetails = getPasswordDetails();
@@ -275,7 +275,7 @@ public class AccountRestServiceTest extends AbstractTestRealmKeycloakTest {
@Test
public void testPasswordConfirmation() throws IOException {
- assumeFeatureEnabled(ACCOUNT2);
+ assumeFeatureEnabled(ACCOUNT_API);
updatePassword("password", "Str0ng3rP4ssw0rd", "confirmationDoesNotMatch", 400);
@@ -318,7 +318,7 @@ public class AccountRestServiceTest extends AbstractTestRealmKeycloakTest {
@Test
public void testDeleteSession() throws IOException {
- assumeFeatureEnabled(ACCOUNT2);
+ assumeFeatureEnabled(ACCOUNT_API);
TokenUtil viewToken = new TokenUtil("view-account-access", "password");
String sessionId = oauth.doLogin("view-account-access", "password").getSessionState();
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/ScriptAuthenticatorTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/ScriptAuthenticatorTest.java
index 9971da7..ec042b2 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/ScriptAuthenticatorTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/ScriptAuthenticatorTest.java
@@ -26,6 +26,7 @@ import org.junit.Rule;
import org.junit.Test;
import org.keycloak.authentication.authenticators.browser.ScriptBasedAuthenticatorFactory;
import org.keycloak.authentication.authenticators.browser.UsernamePasswordFormFactory;
+import org.keycloak.common.Profile;
import org.keycloak.events.Details;
import org.keycloak.events.Errors;
import org.keycloak.events.EventType;
@@ -64,6 +65,11 @@ public class ScriptAuthenticatorTest extends AbstractFlowTest {
public static final String EXECUTION_ID = "scriptAuth";
+ @BeforeClass
+ public static void verifyEnvironment() {
+ ProfileAssume.assumeFeatureEnabled(Profile.Feature.SCRIPTS);
+ }
+
@Override
public void configureTestRealm(RealmRepresentation testRealm) {
diff --git a/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties b/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties
index 7876630..4c1c915 100644
--- a/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties
+++ b/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties
@@ -1121,11 +1121,17 @@ include-representation.tooltip=Include JSON representation for create and update
clear-admin-events.tooltip=Deletes all admin events in the database.
server-version=Server Version
server-profile=Server Profile
-server-disabled=Server Disabled Features
+server-disabled=Disabled Features
+server-disabled.tooltip=Features that are not currently enabled. Some features are not enabled by default. This applies to all preview and experimental features.
+server-preview=Preview Features
+server-preview.tooltip=Preview features are not supported in production use and may be significantly changed or removed in the future.
+server-experimental=Experimental Features
+server-experimental.tooltip=Experimental features are experimental features that may not be fully function. Never use experimental features in production.
info=Info
providers=Providers
server-time=Server Time
server-uptime=Server Uptime
+profile=Profile
memory=Memory
total-memory=Total Memory
free-memory=Free Memory
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/server-info.html b/themes/src/main/resources/theme/base/admin/resources/partials/server-info.html
index 4a4b296..6d24419 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/server-info.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/server-info.html
@@ -15,14 +15,6 @@
<td>{{serverInfo.systemInfo.version}}</td>
</tr>
<tr>
- <td width="20%">{{:: 'server-profile' | translate}}</td>
- <td>{{serverInfo.profileInfo.name | capitalize}}</td>
- </tr>
- <tr data-ng-if="serverInfo.profileInfo.disabledFeatures.length > 0">
- <td width="20%">{{:: 'server-disabled' | translate}}</td>
- <td>{{serverInfo.profileInfo.disabledFeatures.join(', ').toLowerCase() | capitalize}}</td>
- </tr>
- <tr>
<td>{{:: 'server-time' | translate}}</td>
<td>{{serverInfo.systemInfo.serverTime}}</td>
</tr>
@@ -32,6 +24,37 @@
</tr>
</table>
+ <table class="table table-striped table-bordered">
+ <legend>{{:: 'profile' | translate}}</legend>
+
+ <tr>
+ <td width="20%">{{:: 'server-profile' | translate}}</td>
+ <td>{{serverInfo.profileInfo.name | capitalize}}</td>
+ </tr>
+ <tr data-ng-if="serverInfo.profileInfo.disabledFeatures.length > 0">
+ <td width="20%">
+ <span>{{:: 'server-disabled' | translate}}</span>
+ <kc-tooltip>{{:: 'server-disabled.tooltip' | translate}}</kc-tooltip>
+ </td>
+ <td>{{serverInfo.profileInfo.disabledFeatures.sort().join(', ')}}</td>
+
+ </tr>
+ <tr data-ng-if="serverInfo.profileInfo.previewFeatures.length > 0">
+ <td width="20%">
+ <span>{{:: 'server-preview' | translate}}</span>
+ <kc-tooltip>{{:: 'server-preview.tooltip' | translate}}</kc-tooltip>
+ </td>
+ <td>{{serverInfo.profileInfo.previewFeatures.sort().join(', ')}}</td>
+ </tr>
+ <tr data-ng-if="serverInfo.profileInfo.experimentalFeatures.length > 0">
+ <td width="20%">
+ <span>{{:: 'server-experimental' | translate}}</span>
+ <kc-tooltip>{{:: 'server-experimental.tooltip' | translate}}</kc-tooltip>
+ </td>
+ <td>{{serverInfo.profileInfo.experimentalFeatures.sort().join(', ')}}</td>
+ </tr>
+ </table>
+
<fieldset>
<legend>{{:: 'memory' | translate}}</legend>
<table class="table table-striped table-bordered" style="margin-top: 0;">