keycloak-aplcache

Updated themes docs

3/23/2015 6:45:54 AM

Details

diff --git a/docbook/reference/en/en-US/modules/themes.xml b/docbook/reference/en/en-US/modules/themes.xml
index 3996b3a..db3d659 100755
--- a/docbook/reference/en/en-US/modules/themes.xml
+++ b/docbook/reference/en/en-US/modules/themes.xml
@@ -2,18 +2,18 @@
     <title>Themes</title>
 
     <para>
-        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.
     </para>
 
     <section>
         <title>Theme types</title>
         <para>
-            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:
             <itemizedlist>
                 <listitem>Account - Account management</listitem>
                 <listitem>Admin - Admin console</listitem>
-                <listitem>Common - Shared resources for themes</listitem>
                 <listitem>Email - Emails</listitem>
                 <listitem>Login - Login forms</listitem>
                 <listitem>Welcome - Welcome pages</listitem>
@@ -29,6 +29,11 @@
             from the drop-down box in the top left corner. Under <literal>Settings</literal> click on <literal>Theme</literal>.
         </para>
         <para>
+            To set the theme for the <literal>master</literal> Keycloak admin console set the admin console theme for
+            the <literal>master</literal> realm. To set the theme for per realm admin access control set the admin console
+            theme for the corresponding realm.
+        </para>
+        <para>
             To change the welcome theme you need to edit <literal>standalone/configuration/keycloak-server.json</literal>
             and add <literal>welcomeTheme</literal> to the theme element, for example:
 <programlisting>
@@ -43,9 +48,8 @@
     <section>
         <title>Default themes</title>
         <para>
-            Keycloak comes bundled with default themes in <literal>standalone/configuration/themes</literal>. 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 <literal>standalone/configuration/themes</literal>. You should
+            not edit the bundled themes directly. Instead create a new theme that extends a bundled theme.
         </para>
     </section>
 
@@ -65,24 +69,63 @@
         <para>
             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.
+        </para>
+        <para>
+            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 <literal>../standalone/configuration/keycloak-server.json</literal>
+            for <literal>theme</literal> set <literal>staticMaxAge</literal> to <literal>-1</literal> and
+            <literal>cacheTemplates</literal> and <literal>cacheThemes</literal> to <literal>false</literal>. For example:
+<programlisting>[<![CDATA[
+"theme": {
+    "default": "keycloak",
+    "staticMaxAge": 01,
+    "cacheTemplates": false,
+    "cacheThemes": false,
+    "folder": {
+      "dir": "${jboss.server.config.dir}/themes"
+    }
+},
+]]></programlisting>
+            Remember to re-enable caching in production as it will significantly impact performance.
         </para>
         <para>
-            To create a new theme, create a folder in <literal>.../standalone/configuration/themes/&lt;theme type&gt;</literal>.
-            The name of the folder is the name of the theme. Then create a file <literal>theme.properties</literal> inside the theme folder.
-            The contents of the file should be:
+            To create a new theme create a directory for the theme in <literal>.../standalone/configuration/themes</literal>.
+            The name of the directory should be the name of the theme. For example to create a theme called <literal>example-theme</literal>
+            create the directory <literal>.../standalone/configuration/themes/example-theme</literal>. 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 <literal>example-theme</literal> theme create the directory
+            <literal>.../standalone/configuration/themes/example-theme/login</literal>.
         </para>
-        <programlisting>parent=base</programlisting>
         <para>
-            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.</para>
+            For each type create a file <literal>theme.properties</literal> 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 <literal>.../standalone/configuration/themes/example-theme/login/theme.properties</literal> with the
+            following contents:
+<programlisting>[<![CDATA[
+parent=base
+import=common/keycloak
+]]></programlisting>
+        </para>
+        <para>
+            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 <literal>Themes</literal>. For <literal>Login Theme</literal> select
+            <literal>example-theme</literal> and click <literal>Save</literal>. Then open the login page for the realm.
+            You can do this either by login through your application or by opening <literal>http://localhost:8080/realms/&lt;realm name&gt;/account</literal>.
+        </para>
+        <para>
+            To see the effect of changing the parent theme, set <literal>parent=keycloak</literal> in <literal>theme.properties</literal>
+            and refresh the login page. To follow the rest of the documentation set it back to <literal>parent=base</literal>
+            before continuing.
+        </para>
         <section>
             <title>Stylesheets</title>
             <para>
-                A theme can have one or more stylesheets, to add a stylesheet create a file inside <literal>resources/css</literal> (for example <literal>resources/css/styles.css</literal>)
-                inside your theme folder. Then registering it in <literal>theme.properties</literal> by adding:
+                A theme can have one or more stylesheets, to add a stylesheet create a file inside <literal>resources/css</literal>
+                (for example <literal>resources/css/styles.css</literal>) inside your theme folder. Then registering it
+                in <literal>theme.properties</literal> by adding:
             </para>
             <programlisting>styles=css/styles.css</programlisting>
             <para>
@@ -90,6 +133,17 @@
                 as you want. For example:
             </para>
             <programlisting>styles=css/styles.css css/more-styles.css</programlisting>
+            For the example-theme above add <literal>example-theme/login/resources/css/styles.css</literal> with the
+            following content:
+<programlisting>[<![CDATA[
+#kc-form {
+    background-color: #000;
+    color: #fff;
+    padding: 20px;
+}]]></programlisting>
+            Then edit <literal>example-theme/login/theme.properties</literal> and add <programlisting>styles=css/styles.css</programlisting>.
+            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.
         </section>
         <section>
             <title>Scripts</title>
@@ -121,9 +175,8 @@
         <section>
             <title>Messages</title>
             <para>
-                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
                 <literal>Username</literal> on the login form with <literal>Your Username</literal> create the file
                 <literal>messages/messages.properties</literal> inside your theme folder and add the following content:
             </para>
@@ -134,31 +187,80 @@
             <para>
                 Keycloak uses <ulink url="http://freemarker.org">Freemarker Templates</ulink> in order to generate HTML.
                 These templates are defined in <literal>.ftl</literal> 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
+                <literal>example-theme</literal> copy <literal>../standalone/configuration/themes/base/login/login.ftl</literal>
+                to <literal>../standalone/configuration/themes/example-theme/login</literal> and open it in an editor. After
+                the first line (&lt;#import ...&gt;) add <literal>&lt;h1&gt;HELLO WORLD!&lt;/h1&gt;</literal> then refresh
+                the page.
             </para>
         </section>
     </section>
 
     <section>
+        <title>Deploying themes</title>
+        <para>
+            Themes can be deployed to Keycloak by copying the theme directory to <literal>../standalone/configuration/themes</literal>
+            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.
+        </para>
+        <para>
+            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 <literal>META/keycloak-server.json</literal> that describes the themes contained
+            in the archive. For example <literal>example-theme.jar</literal> with the contents:
+            <itemizedlist>
+                <listitem>META-INF/keycloak-themes.json</listitem>
+                <listitem>theme/example-theme/login/theme.properties</listitem>
+                <listitem>theme/example-theme/login/login.ftl</listitem>
+                <listitem>theme/example-theme/login/resources/css/styles.css</listitem>
+            </itemizedlist>
+            The contents of META-INF/keycloak-server.json in this case would be:
+<programlisting>[<![CDATA[
+{
+    "themes": [{
+        "name" : "example-theme",
+        "types": [ "login" ]
+    }]
+}
+]]></programlisting>
+            As you can see a single jar can contain multiple themes and each theme can support one or more types.
+        </para>
+        <para>
+            The deploy the jar as a module to Keycloak you can either manually create the module or use <literal>jboss-cli</literal>.
+            It's simplest to use <literal>jboss-cli</literal> as it creates the required directories and module descriptor
+            for you. To deploy the above jar <literal>jboss-cli</literal> run:
+<programlisting>[<![CDATA[
+    KEYCLOAK_HOME/bin/jboss-cli.sh --command="module add --name=org.example.exampletheme --resources=example-theme.jar"
+]]></programlisting>
+            If you're on windows run <programlisting>KEYCLOAK_HOME/bin/jboss-cli.bat</programlisting>.
+        </para>
+        <para>
+            This command creates <literal>modules/org/example/exampletheme/main</literal> containing <literal>example-theme.jar</literal>
+            and <literal>module.xml</literal>.
+        </para>
+        <para>
+            Once you've created the module you need to register it with Keycloak do this by editing
+            <literal>../standalone/configuration/keycloak-server.json</literal> and adding the module to <literal>theme/module/modules</literal>. For example:
+<programlisting>[<![CDATA[
+"theme": {
+    ...
+    "module": {
+        "modules": [ "org.example.exampletheme" ]
+    }
+}
+]]></programlisting>
+        </para>
+        <para>
+            If a theme is deployed to <literal>../standalone/configuration/themes</literal> and as a module the first
+            is used.
+        </para>
+    </section>
+
+    <section>
         <title>SPIs</title>
         <para>
             For full control of login forms and account management Keycloak provides a number of SPIs.
         </para>
         <section>
-            <title>Theme SPI</title>
-            <para>
-                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
-                <literal>org.keycloak.freemarker.ThemeProviderFactory</literal> and <literal>org.keycloak.freemarker.ThemeProvider</literal>.
-            </para>
-            <para>
-                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
-                <literal>forms/common-themes</literal> on GitHub or the source download.
-            </para>
-        </section>
-        <section>
             <title>Account SPI</title>
             <para>
                 The Account SPI allows implementing the account management pages using whatever web framework or templating
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 2fdaf05..42fa50e 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<ThemeKey, Theme> themeCache = new ConcurrentHashMap<ThemeKey, Theme>();
-
-    private ExtendingThemeManager themeManager;
+    private ConcurrentHashMap<ThemeKey, Theme> 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<ThemeKey, Theme>();
+            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 8f2dc0e..e41d671 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<String, Template>();
+            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 0edc92e..7d9ce2a 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 df65369..90d8ba6 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