Fix issue where admin2 was not enabled by default if account2 was disabled (#14914)
Refactoring ThemeSelector and DefaultThemeManager to re-use the same logic for selecting default theme as there used to be two places where one had a broken implementation Closes #14889
This commit is contained in:
parent
90369f7540
commit
f7490b7f7c
4 changed files with 39 additions and 42 deletions
|
@ -17,6 +17,9 @@
|
||||||
|
|
||||||
package org.keycloak.theme;
|
package org.keycloak.theme;
|
||||||
|
|
||||||
|
import org.keycloak.Config;
|
||||||
|
import org.keycloak.common.Profile;
|
||||||
|
import org.keycloak.common.Version;
|
||||||
import org.keycloak.provider.Provider;
|
import org.keycloak.provider.Provider;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -32,4 +35,14 @@ public interface ThemeSelectorProvider extends Provider {
|
||||||
*/
|
*/
|
||||||
String getThemeName(Theme.Type type);
|
String getThemeName(Theme.Type type);
|
||||||
|
|
||||||
|
default String getDefaultThemeName(Theme.Type type) {
|
||||||
|
String name = Config.scope("theme").get("default", Version.NAME.toLowerCase());
|
||||||
|
if ((type == Theme.Type.ACCOUNT) && Profile.isFeatureEnabled(Profile.Feature.ACCOUNT2)) {
|
||||||
|
name = name.concat(".v2");
|
||||||
|
} else if ((type == Theme.Type.ADMIN) && Profile.isFeatureEnabled(Profile.Feature.ADMIN2)) {
|
||||||
|
name = name.concat(".v2");
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,12 +49,10 @@ public class DefaultThemeManager implements ThemeManager {
|
||||||
private final DefaultThemeManagerFactory factory;
|
private final DefaultThemeManagerFactory factory;
|
||||||
private final KeycloakSession session;
|
private final KeycloakSession session;
|
||||||
private List<ThemeProvider> providers;
|
private List<ThemeProvider> providers;
|
||||||
private final String defaultTheme;
|
|
||||||
|
|
||||||
public DefaultThemeManager(DefaultThemeManagerFactory factory, KeycloakSession session) {
|
public DefaultThemeManager(DefaultThemeManagerFactory factory, KeycloakSession session) {
|
||||||
this.factory = factory;
|
this.factory = factory;
|
||||||
this.session = session;
|
this.session = session;
|
||||||
this.defaultTheme = Config.scope("theme").get("default", Version.NAME.toLowerCase());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -63,44 +61,20 @@ public class DefaultThemeManager implements ThemeManager {
|
||||||
return getTheme(name, type);
|
return getTheme(name, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String typeBasedDefault(Theme.Type type) {
|
|
||||||
boolean isProduct = Profile.isProduct();
|
|
||||||
|
|
||||||
if ((type == Theme.Type.ACCOUNT) && isAccount2Enabled()) {
|
|
||||||
return isProduct ? "rh-sso.v2" : "keycloak.v2";
|
|
||||||
}
|
|
||||||
|
|
||||||
return isProduct ? "rh-sso" : "keycloak";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Theme getTheme(String name, Theme.Type type) {
|
public Theme getTheme(String name, Theme.Type type) {
|
||||||
if (name == null) {
|
|
||||||
name = defaultTheme;
|
|
||||||
}
|
|
||||||
|
|
||||||
Theme theme = factory.getCachedTheme(name, type);
|
Theme theme = factory.getCachedTheme(name, type);
|
||||||
if (theme == null) {
|
if (theme == null) {
|
||||||
theme = loadTheme(name, type);
|
theme = loadTheme(name, type);
|
||||||
if (theme == null) {
|
if (theme == null) {
|
||||||
theme = loadTheme(typeBasedDefault(type), type);
|
String defaultThemeName = session.getProvider(ThemeSelectorProvider.class).getDefaultThemeName(type);
|
||||||
if (theme == null) {
|
theme = loadTheme(defaultThemeName, type);
|
||||||
theme = loadTheme("base", type);
|
|
||||||
}
|
|
||||||
log.errorv("Failed to find {0} theme {1}, using built-in themes", type, name);
|
log.errorv("Failed to find {0} theme {1}, using built-in themes", type, name);
|
||||||
} else {
|
} else {
|
||||||
theme = factory.addCachedTheme(name, type, theme);
|
theme = factory.addCachedTheme(name, type, theme);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isAccount2Enabled() && theme.getName().equals("keycloak.v2")) {
|
|
||||||
theme = loadTheme("keycloak", type);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isAccount2Enabled() && theme.getName().equals("rh-sso.v2")) {
|
|
||||||
theme = loadTheme("rh-sso", type);
|
|
||||||
}
|
|
||||||
|
|
||||||
return theme;
|
return theme;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,12 +47,7 @@ public class DefaultThemeSelectorProvider implements ThemeSelectorProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name == null || name.isEmpty()) {
|
if (name == null || name.isEmpty()) {
|
||||||
name = Config.scope("theme").get("default", Version.NAME.toLowerCase());
|
name = getDefaultThemeName(type);
|
||||||
if ((type == Theme.Type.ACCOUNT) && Profile.isFeatureEnabled(Profile.Feature.ACCOUNT2)) {
|
|
||||||
name = name.concat(".v2");
|
|
||||||
} else if ((type == Theme.Type.ADMIN) && Profile.isFeatureEnabled(Profile.Feature.ADMIN2)) {
|
|
||||||
name = name.concat(".v2");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return name;
|
return name;
|
||||||
|
|
|
@ -13,11 +13,12 @@ import org.keycloak.testsuite.AbstractKeycloakTest;
|
||||||
import org.keycloak.testsuite.arquillian.annotation.DisableFeature;
|
import org.keycloak.testsuite.arquillian.annotation.DisableFeature;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
@DisableFeature(value = Profile.Feature.ACCOUNT2, skipRestart = true) // TODO remove this (KEYCLOAK-16228)
|
|
||||||
public class AdminConsoleLandingPageTest extends AbstractKeycloakTest {
|
public class AdminConsoleLandingPageTest extends AbstractKeycloakTest {
|
||||||
|
|
||||||
private CloseableHttpClient client;
|
private CloseableHttpClient client;
|
||||||
|
@ -44,16 +45,14 @@ public class AdminConsoleLandingPageTest extends AbstractKeycloakTest {
|
||||||
public void landingPage() throws IOException {
|
public void landingPage() throws IOException {
|
||||||
String body = SimpleHttp.doGet(suiteContext.getAuthServerInfo().getContextRoot() + "/auth/admin/master/console", client).asString();
|
String body = SimpleHttp.doGet(suiteContext.getAuthServerInfo().getContextRoot() + "/auth/admin/master/console", client).asString();
|
||||||
|
|
||||||
String authUrl = body.substring(body.indexOf("var authUrl = '") + 15);
|
Map<String, String> config = getConfig(body);
|
||||||
authUrl = authUrl.substring(0, authUrl.indexOf("'"));
|
String authUrl = config.get("authUrl");
|
||||||
Assert.assertEquals(suiteContext.getAuthServerInfo().getContextRoot() + "/auth", authUrl);
|
Assert.assertEquals(suiteContext.getAuthServerInfo().getContextRoot() + "/auth", authUrl);
|
||||||
|
|
||||||
String resourceUrl = body.substring(body.indexOf("var resourceUrl = '") + 19);
|
String resourceUrl = config.get("resourceUrl");
|
||||||
resourceUrl = resourceUrl.substring(0, resourceUrl.indexOf("'"));
|
Assert.assertTrue(resourceUrl.matches("/auth/resources/[^/]*/admin/keycloak.v2"));
|
||||||
Assert.assertTrue(resourceUrl.matches("/auth/resources/[^/]*/admin/([a-z]*|[a-z]*-[a-z]*)"));
|
|
||||||
|
|
||||||
String consoleBaseUrl = body.substring(body.indexOf("var consoleBaseUrl = '") + 22);
|
String consoleBaseUrl = config.get("consoleBaseUrl");
|
||||||
consoleBaseUrl = consoleBaseUrl.substring(0, consoleBaseUrl.indexOf("'"));
|
|
||||||
Assert.assertEquals(consoleBaseUrl, "/auth/admin/master/console/");
|
Assert.assertEquals(consoleBaseUrl, "/auth/admin/master/console/");
|
||||||
|
|
||||||
Pattern p = Pattern.compile("link href=\"([^\"]*)\"");
|
Pattern p = Pattern.compile("link href=\"([^\"]*)\"");
|
||||||
|
@ -77,4 +76,20 @@ public class AdminConsoleLandingPageTest extends AbstractKeycloakTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Map<String, String> getConfig(String body) {
|
||||||
|
Map<String, String> variables = new HashMap<>();
|
||||||
|
String start = "<script id=\"environment\" type=\"application/json\">";
|
||||||
|
String end = "</script>";
|
||||||
|
|
||||||
|
String config = body.substring(body.indexOf(start) + start.length());
|
||||||
|
config = config.substring(0, config.indexOf(end)).trim();
|
||||||
|
|
||||||
|
Matcher matcher = Pattern.compile(".*\"(.*)\": \"(.*)\"").matcher(config);
|
||||||
|
while (matcher.find()) {
|
||||||
|
variables.put(matcher.group(1), matcher.group(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
return variables;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue