keycloak-aplcache

Merge pull request #1070 from stianst/jar-theme KEYCLOAK-498

3/20/2015 10:14:09 AM

Changes

forms/common-themes/src/main/java/org/keycloak/theme/DefaultKeycloakThemeProvider.java 79(+0 -79)

forms/common-themes/src/main/java/org/keycloak/theme/DefaultKeycloakThemeProviderFactory.java 41(+0 -41)

project-integrations/aerogear-ups/auth-server/src/main/java/org/aerogear/ups/security/AerogearThemeProviderFactory.java 40(+0 -40)

project-integrations/aerogear-ups/auth-server/src/main/resources/META-INF/services/org.keycloak.freemarker.ThemeProviderFactory 1(+0 -1)

Details

diff --git a/examples/themes/pom.xml b/examples/themes/pom.xml
new file mode 100755
index 0000000..842c117
--- /dev/null
+++ b/examples/themes/pom.xml
@@ -0,0 +1,30 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.2.0.Beta1-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+    <name>Themes Examples</name>
+    <description/>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-example-themes</artifactId>
+    <packaging>jar</packaging>
+
+    <build>
+        <finalName>keycloak-example-themes</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-deploy-plugin</artifactId>
+                <configuration>
+                    <skip>true</skip>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+    <modules>
+    </modules>
+</project>
diff --git a/examples/themes/README.md b/examples/themes/README.md
index fccb847..9f555bc 100644
--- a/examples/themes/README.md
+++ b/examples/themes/README.md
@@ -6,7 +6,24 @@ Sunrise Login Theme
 
 Example login theme that changes the look of the login forms.
 
-To use the theme copy `login/sunrise` to `standalone/configuration/themes/login/`. Open the admin console, select your realm, click on `Theme`. In the dropdown for `Login Theme` select `sunrise`. Click `Save` and login to the realm to see the new theme in action.
+To use the theme you can either deploy it as a module or copy it to the Keycloaks themes folder.
+
+To deploy as a module run:
+
+   mvn clean install
+   $KEYCLOAK_HOME/bin/jboss-cli.sh --command="module add --name=org.keycloak.example.sunrisetheme --resources=target/keycloak-example-themes.jar"
+
+Then open $KEYCLOAK_HOME/standalone/configuration/keycloak-server.json and register the theme module by adding:
+    
+   "theme": {
+       "module": {
+           "modules": [ "org.keycloak.example.sunrisetheme" ]
+       }
+   }
+
+Alternatively you can copy `src/main/resources/theme/login` to `standalone/configuration/themes/login/`. 
+
+Once you've added the theme open the admin console, select your realm, click on `Theme`. In the dropdown for `Login Theme` select `sunrise`. Click `Save` and login to the realm to see the new theme in action.
 
 
 Change Logo Theme
@@ -14,14 +31,30 @@ Change Logo Theme
 
 Example themes for login forms, account management, admin console and welcome pages that changes the Keycloak logo.
 
-To use the themes copy:
+To use the themes you can either deploy it as a module or copy it to the Keycloaks themes folder.
+
+To deploy as a module run:
+
+   mvn clean install
+   $KEYCLOAK_HOME/bin/jboss-cli.sh --command="module add --name=org.keycloak.example.logotheme --resources=target/keycloak-example-themes.jar"
+
+Then open $KEYCLOAK_HOME/standalone/configuration/keycloak-server.json and register the theme module by adding:
+    
+   "theme": {
+       "module": {
+           "modules": [ "org.keycloak.example.logotheme" ]
+       }
+   }
+
+Alternatively you can copy:
 
 * `account/logo-example` to `standalone/configuration/themes/account/`
 * `login/logo-example` to `standalone/configuration/themes/login/`
 * `admin/logo-example` to `standalone/configuration/themes/admin/`
 * `welcome/logo-example` to `standalone/configuration/themes/welcome/`
 
-Open the admin console, select your realm, click on `Theme`. In the dropdowns for `Login Theme`, `Account Theme` and `Admin Console Theme` select `logo-example`. Click `Save` and login to the realm to see the new theme in action.
+
+Once you've added the theme open the admin console, select your realm, click on `Theme`. In the dropdowns for `Login Theme`, `Account Theme` and `Admin Console Theme` select `logo-example`. Click `Save` and login to the realm to see the new theme in action.
 
 To change the theme for the welcome pages open `standalone/configuration/keycloak-server.json` find the config for `theme` and add 'welcomeTheme':
 
diff --git a/examples/themes/src/main/resources/META-INF/keycloak-themes.json b/examples/themes/src/main/resources/META-INF/keycloak-themes.json
new file mode 100644
index 0000000..12ee694
--- /dev/null
+++ b/examples/themes/src/main/resources/META-INF/keycloak-themes.json
@@ -0,0 +1,9 @@
+{
+    "themes": [{
+        "name" : "logo-example",
+        "types": [ "admin", "account", "login", "welcome" ]
+    }, {
+        "name" : "sunrise",
+        "types": [ "login" ]
+    }]
+}
diff --git a/forms/common-themes/pom.xml b/forms/common-themes/pom.xml
index 04ea6bc..70b057b 100755
--- a/forms/common-themes/pom.xml
+++ b/forms/common-themes/pom.xml
@@ -47,6 +47,11 @@
             <artifactId>jboss-logging</artifactId>
             <scope>provided</scope>
         </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-core-asl</artifactId>
+            <scope>provided</scope>
+        </dependency>
 	</dependencies>
 
 	<build>
diff --git a/forms/common-themes/src/main/java/org/keycloak/theme/JarThemeProviderFactory.java b/forms/common-themes/src/main/java/org/keycloak/theme/JarThemeProviderFactory.java
new file mode 100644
index 0000000..bcd0316
--- /dev/null
+++ b/forms/common-themes/src/main/java/org/keycloak/theme/JarThemeProviderFactory.java
@@ -0,0 +1,110 @@
+package org.keycloak.theme;
+
+import org.keycloak.Config;
+import org.keycloak.freemarker.Theme;
+import org.keycloak.freemarker.ThemeProvider;
+import org.keycloak.freemarker.ThemeProviderFactory;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.util.JsonSerialization;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class JarThemeProviderFactory implements ThemeProviderFactory {
+
+    protected static final String KEYCLOAK_THEMES_JSON = "META-INF/keycloak-themes.json";
+    protected static Map<Theme.Type, Map<String, ClassLoaderTheme>> themes = new HashMap<>();
+
+    public static class ThemeRepresentation {
+        private String name;
+        private String[] types;
+
+        public String getName() {
+            return name;
+        }
+
+        public void setName(String name) {
+            this.name = name;
+        }
+
+        public String[] getTypes() {
+            return types;
+        }
+
+        public void setTypes(String[] types) {
+            this.types = types;
+        }
+    }
+
+    public static class ThemesRepresentation {
+        private ThemeRepresentation[] themes;
+
+        public ThemeRepresentation[] getThemes() {
+            return themes;
+        }
+
+        public void setThemes(ThemeRepresentation[] themes) {
+            this.themes = themes;
+        }
+    }
+
+    @Override
+    public ThemeProvider create(KeycloakSession session) {
+        return new JarThemeProvider(themes);
+    }
+
+    @Override
+    public void init(Config.Scope config) {
+        try {
+            ClassLoader classLoader = getClass().getClassLoader();
+            Enumeration<URL> resources = classLoader.getResources(KEYCLOAK_THEMES_JSON);
+            while (resources.hasMoreElements()) {
+                loadThemes(classLoader, resources.nextElement().openStream());
+            }
+        } catch (IOException e) {
+            throw new RuntimeException("Failed to load themes", e);
+        }
+    }
+
+    @Override
+    public void postInit(KeycloakSessionFactory factory) {
+    }
+
+    @Override
+    public void close() {
+    }
+
+    @Override
+    public String getId() {
+        return "jar";
+    }
+
+    protected void loadThemes(ClassLoader classLoader, InputStream themesInputStream) {
+        try {
+            ThemesRepresentation themesRep = JsonSerialization.readValue(themesInputStream, ThemesRepresentation.class);
+
+            for (ThemeRepresentation themeRep : themesRep.getThemes()) {
+                for (String t : themeRep.getTypes()) {
+                    Theme.Type type = Theme.Type.valueOf(t.toUpperCase());
+                    if (!themes.containsKey(type)) {
+                        themes.put(type, new HashMap<String, ClassLoaderTheme>());
+                    }
+                    themes.get(type).put(themeRep.getName(), new ClassLoaderTheme(themeRep.getName(), type, classLoader));
+                }
+            }
+        } catch (Exception e) {
+            throw new RuntimeException("Failed to load themes", e);
+        }
+    }
+
+}
diff --git a/forms/common-themes/src/main/resources/META-INF/keycloak-themes.json b/forms/common-themes/src/main/resources/META-INF/keycloak-themes.json
new file mode 100644
index 0000000..d9f09bd
--- /dev/null
+++ b/forms/common-themes/src/main/resources/META-INF/keycloak-themes.json
@@ -0,0 +1,12 @@
+{
+    "themes": [{
+        "name" : "base",
+        "types": [ "admin", "account", "login" ]
+    }, {
+        "name" : "patternfly",
+        "types": [ "admin", "account", "login" ]
+    }, {
+        "name" : "keycloak",
+        "types": [ "admin", "account", "login", "common", "email", "welcome" ]
+    }]
+}
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/META-INF/services/org.keycloak.freemarker.ThemeProviderFactory b/forms/common-themes/src/main/resources/META-INF/services/org.keycloak.freemarker.ThemeProviderFactory
index c1b32dc..ae680da 100644
--- a/forms/common-themes/src/main/resources/META-INF/services/org.keycloak.freemarker.ThemeProviderFactory
+++ b/forms/common-themes/src/main/resources/META-INF/services/org.keycloak.freemarker.ThemeProviderFactory
@@ -1,2 +1,2 @@
-org.keycloak.theme.DefaultKeycloakThemeProviderFactory
+org.keycloak.theme.JarThemeProviderFactory
 org.keycloak.theme.FolderThemeProviderFactory
\ No newline at end of file
diff --git a/integration/wildfly-extensions/pom.xml b/integration/wildfly-extensions/pom.xml
index e627d32..4e19872 100755
--- a/integration/wildfly-extensions/pom.xml
+++ b/integration/wildfly-extensions/pom.xml
@@ -43,6 +43,18 @@
         </dependency>
         <dependency>
             <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-forms-common-freemarker</artifactId>
+            <version>${project.version}</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-forms-common-themes</artifactId>
+            <version>${project.version}</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
             <artifactId>keycloak-services</artifactId>
             <version>${project.version}</version>
             <scope>provided</scope>
diff --git a/integration/wildfly-extensions/src/main/java/org/keycloak/provider/wildfly/ModuleThemeProviderFactory.java b/integration/wildfly-extensions/src/main/java/org/keycloak/provider/wildfly/ModuleThemeProviderFactory.java
new file mode 100644
index 0000000..231ff07
--- /dev/null
+++ b/integration/wildfly-extensions/src/main/java/org/keycloak/provider/wildfly/ModuleThemeProviderFactory.java
@@ -0,0 +1,35 @@
+package org.keycloak.provider.wildfly;
+
+import org.jboss.modules.Module;
+import org.jboss.modules.ModuleClassLoader;
+import org.jboss.modules.ModuleIdentifier;
+import org.keycloak.Config;
+import org.keycloak.theme.JarThemeProviderFactory;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class ModuleThemeProviderFactory extends JarThemeProviderFactory {
+
+    @Override
+    public void init(Config.Scope config) {
+        String[] modules = config.getArray("modules");
+        if (modules != null) {
+            try {
+                for (String moduleSpec : modules) {
+                    Module module = Module.getContextModuleLoader().loadModule(ModuleIdentifier.fromString(moduleSpec));
+                    ModuleClassLoader classLoader = module.getClassLoader();
+                    loadThemes(classLoader, classLoader.getResourceAsStream(KEYCLOAK_THEMES_JSON));
+                }
+            } catch (Exception e) {
+                throw new RuntimeException("Failed to load themes", e);
+            }
+        }
+    }
+
+    @Override
+    public String getId() {
+        return "module";
+    }
+
+}
diff --git a/integration/wildfly-extensions/src/main/resources/META-INF/services/org.keycloak.freemarker.ThemeProviderFactory b/integration/wildfly-extensions/src/main/resources/META-INF/services/org.keycloak.freemarker.ThemeProviderFactory
new file mode 100644
index 0000000..c5515a6
--- /dev/null
+++ b/integration/wildfly-extensions/src/main/resources/META-INF/services/org.keycloak.freemarker.ThemeProviderFactory
@@ -0,0 +1 @@
+org.keycloak.provider.wildfly.ModuleThemeProviderFactory
\ No newline at end of file
diff --git a/project-integrations/aerogear-ups/auth-server/src/main/resources/META-INF/keycloak-themes.json b/project-integrations/aerogear-ups/auth-server/src/main/resources/META-INF/keycloak-themes.json
new file mode 100644
index 0000000..09db937
--- /dev/null
+++ b/project-integrations/aerogear-ups/auth-server/src/main/resources/META-INF/keycloak-themes.json
@@ -0,0 +1,6 @@
+{
+    "themes": [{
+        "name" : "aerogear",
+        "types": [ "admin", "account", "login" ]
+    }]
+}
\ No newline at end of file