From 1dadfc9726f18ea4a5d27e1d6c2fbc00349ec110 Mon Sep 17 00:00:00 2001 From: Stian Thorgersen Date: Mon, 23 Mar 2015 10:45:54 +0100 Subject: [PATCH] Updated themes docs --- docbook/reference/en/en-US/modules/themes.xml | 174 ++++++++++++++---- .../ExtendingThemeManagerFactory.java | 6 +- .../keycloak/freemarker/FreeMarkerUtil.java | 2 +- .../java/org/keycloak/theme/FolderTheme.java | 6 +- .../keycloak/theme/FolderThemeProvider.java | 2 +- 5 files changed, 146 insertions(+), 44 deletions(-) diff --git a/docbook/reference/en/en-US/modules/themes.xml b/docbook/reference/en/en-US/modules/themes.xml index 3996b3a0b05..db3d659a48b 100755 --- a/docbook/reference/en/en-US/modules/themes.xml +++ b/docbook/reference/en/en-US/modules/themes.xml @@ -2,18 +2,18 @@ Themes - Keycloak provides theme support for login forms and account management. This allows customizing the look - and feel of end-user facing pages so they can be integrated with your brand and applications. + Keycloak provides theme support for web pages and emails. This allows customizing the look + and feel of end-user facing pages so they can be integrated with your applications.
Theme types - There are several types of themes in Keycloak: + A theme can support several types to customize different aspects of Keycloak. The types currently available + are: Account - Account management Admin - Admin console - Common - Shared resources for themes Email - Emails Login - Login forms Welcome - Welcome pages @@ -28,6 +28,11 @@ the theme used for a realm open the Keycloak Admin Console, select your realm from the drop-down box in the top left corner. Under Settings click on Theme. + + To set the theme for the master Keycloak admin console set the admin console theme for + the master realm. To set the theme for per realm admin access control set the admin console + theme for the corresponding realm. + To change the welcome theme you need to edit standalone/configuration/keycloak-server.json and add welcomeTheme to the theme element, for example: @@ -43,9 +48,8 @@
Default themes - Keycloak comes bundled with default themes in standalone/configuration/themes. It is - not recommended to edit these themes directly. Instead you should create a new theme to extend a default - theme. A good reference is to copy the keycloak themes as these extend the base theme to add styling. + Keycloak comes bundled with default themes in standalone/configuration/themes. You should + not edit the bundled themes directly. Instead create a new theme that extends a bundled theme.
@@ -65,24 +69,63 @@ A theme can extend another theme. When extending a theme you can override individual files (templates, stylesheets, etc.). The recommended way to create a theme is to extend the base theme. The base theme provides templates - and a default message bundle. It should be possible to achieve the customization required by styling these - templates. + and a default message bundle. If you decide to override templates bear in mind that you may need to update + your templates when upgrading to a new release to include any changes made to the original template. - To create a new theme, create a folder in .../standalone/configuration/themes/<theme type>. - The name of the folder is the name of the theme. Then create a file theme.properties inside the theme folder. - The contents of the file should be: + Before creating a theme it's a good idea to disable caching as this makes it possible to edit theme resources + without restarting the server. To do this open ../standalone/configuration/keycloak-server.json + for theme set staticMaxAge to -1 and + cacheTemplates and cacheThemes to false. For example: +[ + Remember to re-enable caching in production as it will significantly impact performance. - parent=base - You have now created your theme. Check that it works by configuring it for a realm. It should look the same - as the base theme as you've not added anything to it yet. The next sections will describe how to modify - the theme. + To create a new theme create a directory for the theme in .../standalone/configuration/themes. + The name of the directory should be the name of the theme. For example to create a theme called example-theme + create the directory .../standalone/configuration/themes/example-theme. Inside the theme + directory you then need to create a directory for each of the types your theme is going to provide. For example + to add the login type to the example-theme theme create the directory + .../standalone/configuration/themes/example-theme/login. +
+ + For each type create a file theme.properties which allows setting some configuration for + the theme, for example what theme it overrides and if it should import any themes. For the above example we + want to override the base theme and import common resources from the Keycloak theme. To do this create the + file .../standalone/configuration/themes/example-theme/login/theme.properties with the + following contents: +[ + + + You have now created a theme with support for the login type. To check that it works open the admin console. + Select your realm and click on Themes. For Login Theme select + example-theme and click Save. Then open the login page for the realm. + You can do this either by login through your application or by opening http://localhost:8080/realms/<realm name>/account. + + + To see the effect of changing the parent theme, set parent=keycloak in theme.properties + and refresh the login page. To follow the rest of the documentation set it back to parent=base + before continuing. +
Stylesheets - A theme can have one or more stylesheets, to add a stylesheet create a file inside resources/css (for example resources/css/styles.css) - inside your theme folder. Then registering it in theme.properties by adding: + A theme can have one or more stylesheets, to add a stylesheet create a file inside resources/css + (for example resources/css/styles.css) inside your theme folder. Then registering it + in theme.properties by adding: styles=css/styles.css @@ -90,6 +133,17 @@ as you want. For example: styles=css/styles.css css/more-styles.css + For the example-theme above add example-theme/login/resources/css/styles.css with the + following content: +[ + Then edit example-theme/login/theme.properties and add styles=css/styles.css. + Refresh the login page to see your changes. It's not pretty, but you can see how easily you can modify the + styles for your theme.
Scripts @@ -121,9 +175,8 @@
Messages - Text in the templates are loaded from message bundles. Currently internationalization isn't supported, - but that will be added in a later release. A theme that extends another theme will inherit all messages - from the parents message bundle, but can override individual messages. For example to replace + Text in the templates are loaded from message bundles. A theme that extends another theme will inherit + all messages from the parents message bundle, but can override individual messages. For example to replace Username on the login form with Your Username create the file messages/messages.properties inside your theme folder and add the following content: @@ -134,30 +187,79 @@ Keycloak uses Freemarker Templates in order to generate HTML. These templates are defined in .ftl files and can be overriden from the base theme. - Check out the Freemarker website on how to form a template file. + Check out the Freemarker website on how to form a template file. To override the login template for the + example-theme copy ../standalone/configuration/themes/base/login/login.ftl + to ../standalone/configuration/themes/example-theme/login and open it in an editor. After + the first line (<#import ...>) add <h1>HELLO WORLD!</h1> then refresh + the page.
+
+ Deploying themes + + Themes can be deployed to Keycloak by copying the theme directory to ../standalone/configuration/themes + or it can be deployed as a module. For a single server or during development just copying the theme is fine, but + in a cluster or domain it's recommended to deploy as a module. + + + To deploy a theme as a module you need to create an jar (it's basically just a zip with jar extension) with + the theme resources and a file META/keycloak-server.json that describes the themes contained + in the archive. For example example-theme.jar with the contents: + + META-INF/keycloak-themes.json + theme/example-theme/login/theme.properties + theme/example-theme/login/login.ftl + theme/example-theme/login/resources/css/styles.css + + The contents of META-INF/keycloak-server.json in this case would be: +[ + As you can see a single jar can contain multiple themes and each theme can support one or more types. + + + The deploy the jar as a module to Keycloak you can either manually create the module or use jboss-cli. + It's simplest to use jboss-cli as it creates the required directories and module descriptor + for you. To deploy the above jar jboss-cli run: +[ + If you're on windows run KEYCLOAK_HOME/bin/jboss-cli.bat. + + + This command creates modules/org/example/exampletheme/main containing example-theme.jar + and module.xml. + + + Once you've created the module you need to register it with Keycloak do this by editing + ../standalone/configuration/keycloak-server.json and adding the module to theme/module/modules. For example: +[ + + + If a theme is deployed to ../standalone/configuration/themes and as a module the first + is used. + +
+
SPIs For full control of login forms and account management Keycloak provides a number of SPIs. -
- Theme SPI - - The Theme SPI allows creating different mechanisms to load themes for the default FreeMarker based - implementations of login forms and account management. To create a theme provider you will need to implement - org.keycloak.freemarker.ThemeProviderFactory and org.keycloak.freemarker.ThemeProvider. - - - Keycloak comes with two theme providers, one that loads themes from the classpath (used by default themes) - and another that loads themes from a folder (used by custom themes). Looking at these - would be a good place to start to create your own theme provider. You can find them inside - forms/common-themes on GitHub or the source download. - -
Account SPI diff --git a/forms/common-freemarker/src/main/java/org/keycloak/freemarker/ExtendingThemeManagerFactory.java b/forms/common-freemarker/src/main/java/org/keycloak/freemarker/ExtendingThemeManagerFactory.java index 2fdaf0513cb..42fa50e3610 100755 --- a/forms/common-freemarker/src/main/java/org/keycloak/freemarker/ExtendingThemeManagerFactory.java +++ b/forms/common-freemarker/src/main/java/org/keycloak/freemarker/ExtendingThemeManagerFactory.java @@ -11,9 +11,7 @@ import java.util.concurrent.ConcurrentHashMap; */ public class ExtendingThemeManagerFactory implements ThemeProviderFactory { - private ConcurrentHashMap themeCache = new ConcurrentHashMap(); - - private ExtendingThemeManager themeManager; + private ConcurrentHashMap themeCache; @Override public ThemeProvider create(KeycloakSession session) { @@ -23,7 +21,7 @@ public class ExtendingThemeManagerFactory implements ThemeProviderFactory { @Override public void init(Config.Scope config) { if(Config.scope("theme").getBoolean("cacheThemes", true)) { - themeCache = new ConcurrentHashMap(); + themeCache = new ConcurrentHashMap<>(); } } diff --git a/forms/common-freemarker/src/main/java/org/keycloak/freemarker/FreeMarkerUtil.java b/forms/common-freemarker/src/main/java/org/keycloak/freemarker/FreeMarkerUtil.java index 8f2dc0e534b..e41d671c28a 100755 --- a/forms/common-freemarker/src/main/java/org/keycloak/freemarker/FreeMarkerUtil.java +++ b/forms/common-freemarker/src/main/java/org/keycloak/freemarker/FreeMarkerUtil.java @@ -20,7 +20,7 @@ public class FreeMarkerUtil { public FreeMarkerUtil() { if (Config.scope("theme").getBoolean("cacheTemplates", true)) { - cache = new ConcurrentHashMap(); + cache = new ConcurrentHashMap<>(); } } diff --git a/forms/common-themes/src/main/java/org/keycloak/theme/FolderTheme.java b/forms/common-themes/src/main/java/org/keycloak/theme/FolderTheme.java index 0edc92ee5fb..7d9ce2abb8a 100644 --- a/forms/common-themes/src/main/java/org/keycloak/theme/FolderTheme.java +++ b/forms/common-themes/src/main/java/org/keycloak/theme/FolderTheme.java @@ -18,11 +18,13 @@ public class FolderTheme implements Theme { private String parentName; private String importName; private File themeDir; + private String name; private Type type; private final Properties properties; - public FolderTheme(File themeDir, Type type) throws IOException { + public FolderTheme(File themeDir, String name, Type type) throws IOException { this.themeDir = themeDir; + this.name = name; this.type = type; this.properties = new Properties(); @@ -36,7 +38,7 @@ public class FolderTheme implements Theme { @Override public String getName() { - return themeDir.getName(); + return name; } @Override diff --git a/forms/common-themes/src/main/java/org/keycloak/theme/FolderThemeProvider.java b/forms/common-themes/src/main/java/org/keycloak/theme/FolderThemeProvider.java index df653699bb4..90d8ba66bf0 100755 --- a/forms/common-themes/src/main/java/org/keycloak/theme/FolderThemeProvider.java +++ b/forms/common-themes/src/main/java/org/keycloak/theme/FolderThemeProvider.java @@ -29,7 +29,7 @@ public class FolderThemeProvider implements ThemeProvider { @Override public Theme getTheme(String name, Theme.Type type) throws IOException { File themeDir = getThemeDir(name, type); - return themeDir.isDirectory() ? new FolderTheme(themeDir, type) : null; + return themeDir.isDirectory() ? new FolderTheme(themeDir, name, type) : null; } @Override