keycloak-memoizeit
Details
forms/pom.xml 4(+4 -0)
diff --git a/forms/pom.xml b/forms/pom.xml
index 8338766..0ad2957 100755
--- a/forms/pom.xml
+++ b/forms/pom.xml
@@ -56,6 +56,10 @@
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.freemarker</groupId>
+ <artifactId>freemarker</artifactId>
+ </dependency>
</dependencies>
<build>
diff --git a/forms/src/main/java/org/keycloak/forms/ErrorBean.java b/forms/src/main/java/org/keycloak/forms/ErrorBean.java
index d184125..ff140bd 100644
--- a/forms/src/main/java/org/keycloak/forms/ErrorBean.java
+++ b/forms/src/main/java/org/keycloak/forms/ErrorBean.java
@@ -21,33 +21,19 @@
*/
package org.keycloak.forms;
-import javax.annotation.PostConstruct;
-import javax.faces.bean.ManagedBean;
-import javax.faces.bean.RequestScoped;
-import javax.faces.context.FacesContext;
-import javax.servlet.http.HttpServletRequest;
-
-import org.keycloak.services.resources.flows.FormFlows;
-
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
-@ManagedBean(name = "error")
-@RequestScoped
public class ErrorBean {
private String summary;
- @PostConstruct
- public void init() {
- FacesContext ctx = FacesContext.getCurrentInstance();
- HttpServletRequest request = (HttpServletRequest) ctx.getExternalContext().getRequest();
-
- summary = (String) request.getAttribute(FormFlows.ERROR_MESSAGE);
+ public ErrorBean(String summary) {
+ this.summary = summary;
}
public String getSummary() {
return summary;
}
-}
+}
\ No newline at end of file
diff --git a/forms/src/main/java/org/keycloak/forms/LoginBean.java b/forms/src/main/java/org/keycloak/forms/LoginBean.java
index a028886..5777e91 100644
--- a/forms/src/main/java/org/keycloak/forms/LoginBean.java
+++ b/forms/src/main/java/org/keycloak/forms/LoginBean.java
@@ -24,25 +24,15 @@ package org.keycloak.forms;
import java.util.LinkedList;
import java.util.List;
-import javax.annotation.PostConstruct;
-import javax.faces.bean.ManagedBean;
-import javax.faces.bean.ManagedProperty;
-import javax.faces.bean.RequestScoped;
-import javax.faces.context.FacesContext;
-import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.core.MultivaluedMap;
import org.keycloak.forms.model.RequiredCredential;
-import org.keycloak.services.resources.flows.FormFlows;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
-@ManagedBean(name = "login")
-@RequestScoped
public class LoginBean {
- @ManagedProperty(value = "#{realm}")
private RealmBean realm;
private String username;
@@ -51,13 +41,10 @@ public class LoginBean {
private List<RequiredCredential> requiredCredentials;
- @PostConstruct
- public void init() {
- FacesContext ctx = FacesContext.getCurrentInstance();
- HttpServletRequest request = (HttpServletRequest) ctx.getExternalContext().getRequest();
+ public LoginBean(RealmBean realm, MultivaluedMap<String, String> formData){
+
+ this.realm = realm;
- @SuppressWarnings("unchecked")
- MultivaluedMap<String, String> formData = (MultivaluedMap<String, String>) request.getAttribute(FormFlows.DATA);
if (formData != null) {
username = formData.getFirst("username");
password = formData.getFirst("password");
@@ -69,6 +56,7 @@ public class LoginBean {
requiredCredentials.add(new RequiredCredential(c.getType(), c.isSecret(), c.getFormLabel()));
}
}
+
}
public String getUsername() {
diff --git a/forms/src/main/java/org/keycloak/forms/RealmBean.java b/forms/src/main/java/org/keycloak/forms/RealmBean.java
index 8b1dcef..e799b7a 100644
--- a/forms/src/main/java/org/keycloak/forms/RealmBean.java
+++ b/forms/src/main/java/org/keycloak/forms/RealmBean.java
@@ -21,34 +21,21 @@
*/
package org.keycloak.forms;
-import javax.annotation.PostConstruct;
-import javax.faces.bean.ManagedBean;
-import javax.faces.bean.RequestScoped;
-import javax.faces.context.FacesContext;
-import javax.servlet.http.HttpServletRequest;
-
import org.keycloak.services.models.RealmModel;
-import org.keycloak.services.resources.flows.FormFlows;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
-@ManagedBean(name = "realm")
-@RequestScoped
public class RealmBean {
private RealmModel realm;
private boolean saas;
- @PostConstruct
- public void init() {
- FacesContext ctx = FacesContext.getCurrentInstance();
- HttpServletRequest request = (HttpServletRequest) ctx.getExternalContext().getRequest();
-
- realm = (RealmModel) request.getAttribute(FormFlows.REALM);
- saas = RealmModel.DEFAULT_REALM.equals(realm.getName());
+ public RealmBean(RealmModel realmModel) {
+ realm = realmModel;
+ saas = RealmModel.DEFAULT_REALM.equals(realmModel.getName());
}
public String getId() {
@@ -59,7 +46,7 @@ public class RealmBean {
return saas ? "Keycloak" : realm.getName();
}
- RealmModel getRealm() {
+ public RealmModel getRealm() {
return realm;
}
diff --git a/forms/src/main/java/org/keycloak/forms/RegisterBean.java b/forms/src/main/java/org/keycloak/forms/RegisterBean.java
index 77d6a8c..cb8c83d 100755
--- a/forms/src/main/java/org/keycloak/forms/RegisterBean.java
+++ b/forms/src/main/java/org/keycloak/forms/RegisterBean.java
@@ -24,39 +24,23 @@ package org.keycloak.forms;
import java.util.HashMap;
import java.util.Map;
-import javax.annotation.PostConstruct;
-import javax.faces.bean.ManagedBean;
-import javax.faces.bean.ManagedProperty;
-import javax.faces.bean.RequestScoped;
-import javax.faces.context.FacesContext;
-import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.core.MultivaluedMap;
-import org.keycloak.services.resources.flows.FormFlows;
-
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
-@ManagedBean(name = "register")
-@RequestScoped
public class RegisterBean {
- private HashMap<String, String> formData;
+ private Map<String, String> formData = new HashMap<String, String>();
private boolean socialRegistration;
- @PostConstruct
- public void init() {
- FacesContext ctx = FacesContext.getCurrentInstance();
- HttpServletRequest request = (HttpServletRequest) ctx.getExternalContext().getRequest();
+ public RegisterBean(MultivaluedMap<String, String> formData, boolean socialRegistration) {
this.formData = new HashMap<String, String>();
- Boolean socialRegistrationAttr = (Boolean)request.getAttribute(FormFlows.SOCIAL_REGISTRATION);
- this.socialRegistration = socialRegistrationAttr != null && socialRegistrationAttr;
+ this.socialRegistration = socialRegistration;
- @SuppressWarnings("unchecked")
- MultivaluedMap<String, String> formData = (MultivaluedMap<String, String>) request.getAttribute(FormFlows.DATA);
if (formData != null) {
for (String k : formData.keySet()) {
this.formData.put(k, formData.getFirst(k));
diff --git a/forms/src/main/java/org/keycloak/forms/SocialBean.java b/forms/src/main/java/org/keycloak/forms/SocialBean.java
index fab91b1..2492ca9 100644
--- a/forms/src/main/java/org/keycloak/forms/SocialBean.java
+++ b/forms/src/main/java/org/keycloak/forms/SocialBean.java
@@ -26,10 +26,6 @@ import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
-import javax.annotation.PostConstruct;
-import javax.faces.bean.ManagedBean;
-import javax.faces.bean.ManagedProperty;
-import javax.faces.bean.RequestScoped;
import javax.imageio.spi.ServiceRegistry;
import javax.ws.rs.core.UriBuilder;
@@ -39,28 +35,24 @@ import org.keycloak.services.resources.flows.Urls;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
-@ManagedBean(name = "social")
-@RequestScoped
public class SocialBean {
- @ManagedProperty(value = "#{realm}")
private RealmBean realm;
- @ManagedProperty(value = "#{register}")
private RegisterBean registerBean;
- @ManagedProperty(value = "#{url}")
private UrlBean url;
private List<SocialProvider> providers;
- private UriBuilder socialLoginUrlBuilder;
+ public SocialBean(RealmBean realm, RegisterBean registerBean, UrlBean url) {
+ this.realm = realm;
+ this.registerBean = registerBean;
+ this.url = url;
- @PostConstruct
- public void init() {
URI baseURI = url.getBaseURI();
- socialLoginUrlBuilder = UriBuilder.fromUri(Urls.socialRedirectToProviderAuth(baseURI, realm.getId()));
+ UriBuilder socialLoginUrlBuilder = UriBuilder.fromUri(Urls.socialRedirectToProviderAuth(baseURI, realm.getId()));
providers = new LinkedList<SocialProvider>();
for (Iterator<org.keycloak.social.SocialProvider> itr = ServiceRegistry
diff --git a/forms/src/main/java/org/keycloak/forms/TemplateBean.java b/forms/src/main/java/org/keycloak/forms/TemplateBean.java
index 841d5f0..724aa0e 100644
--- a/forms/src/main/java/org/keycloak/forms/TemplateBean.java
+++ b/forms/src/main/java/org/keycloak/forms/TemplateBean.java
@@ -24,23 +24,14 @@ package org.keycloak.forms;
import java.util.HashMap;
import java.util.Map;
-import javax.annotation.PostConstruct;
-import javax.faces.bean.ManagedBean;
-import javax.faces.bean.ManagedProperty;
-import javax.faces.bean.RequestScoped;
-import javax.faces.context.FacesContext;
-
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
-@ManagedBean(name = "template")
-@RequestScoped
public class TemplateBean {
- @ManagedProperty(value = "#{realm}")
private RealmBean realm;
- private String theme;
+ private String theme = "default";
private String themeUrl;
@@ -48,9 +39,9 @@ public class TemplateBean {
private String formsPath;
- @PostConstruct
- public void init() {
- formsPath = FacesContext.getCurrentInstance().getExternalContext().getRequestContextPath() + "/forms";
+
+ public TemplateBean(RealmBean realm, String contextPath) {
+ formsPath = contextPath + "/forms";
// TODO Get theme name from realm
theme = "default";
@@ -60,6 +51,7 @@ public class TemplateBean {
themeConfig.put("styles", themeUrl + "/styles.css");
+ // TODO move this into CSS
if (realm.isSaas()) {
themeConfig.put("logo", themeUrl + "/img/red-hat-logo.png");
themeConfig.put("background", themeUrl + "/img/login-screen-background.jpg");
diff --git a/forms/src/main/java/org/keycloak/forms/TotpBean.java b/forms/src/main/java/org/keycloak/forms/TotpBean.java
index b144574..4ae9cdd 100644
--- a/forms/src/main/java/org/keycloak/forms/TotpBean.java
+++ b/forms/src/main/java/org/keycloak/forms/TotpBean.java
@@ -25,39 +25,28 @@ import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Random;
-import javax.annotation.PostConstruct;
-import javax.faces.application.FacesMessage;
-import javax.faces.bean.ManagedBean;
-import javax.faces.bean.ManagedProperty;
-import javax.faces.bean.RequestScoped;
-import javax.faces.context.FacesContext;
-
import org.picketlink.common.util.Base32;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
-@ManagedBean(name = "totp")
-@RequestScoped
public class TotpBean {
- @ManagedProperty(value = "#{user}")
private UserBean user;
private String totpSecret;
private String totpSecretEncoded;
+ private String contextUrl;
- @PostConstruct
- public void init() {
- FacesContext facesContext = FacesContext.getCurrentInstance();
- FacesMessage facesMessage = new FacesMessage("This is a message");
- facesContext.addMessage(null, facesMessage);
+ public TotpBean(UserBean user, String contextUrl) {
+ this.user = user;
+ this.contextUrl = contextUrl;
totpSecret = randomString(20);
totpSecretEncoded = Base32.encode(totpSecret.getBytes());
}
- private static final String randomString(int length) {
+ private static String randomString(int length) {
String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVW1234567890";
Random r = new Random();
StringBuilder sb = new StringBuilder();
@@ -89,8 +78,7 @@ public class TotpBean {
public String getTotpSecretQrCodeUrl() throws UnsupportedEncodingException {
String contents = URLEncoder.encode("otpauth://totp/keycloak?secret=" + totpSecretEncoded, "utf-8");
- String contextPath = FacesContext.getCurrentInstance().getExternalContext().getRequestContextPath();
- return contextPath + "/forms/qrcode" + "?size=200x200&contents=" + contents;
+ return contextUrl + "/forms/qrcode" + "?size=200x200&contents=" + contents;
}
public UserBean getUser() {
diff --git a/forms/src/main/java/org/keycloak/forms/UrlBean.java b/forms/src/main/java/org/keycloak/forms/UrlBean.java
index f846ee1..b6e2ff3 100644
--- a/forms/src/main/java/org/keycloak/forms/UrlBean.java
+++ b/forms/src/main/java/org/keycloak/forms/UrlBean.java
@@ -23,46 +23,20 @@ package org.keycloak.forms;
import java.net.URI;
-import javax.annotation.PostConstruct;
-import javax.faces.bean.ManagedBean;
-import javax.faces.bean.ManagedProperty;
-import javax.faces.bean.RequestScoped;
-import javax.faces.context.FacesContext;
-import javax.servlet.http.HttpServletRequest;
-import javax.ws.rs.core.UriBuilder;
-
-import org.keycloak.services.resources.flows.FormFlows;
import org.keycloak.services.resources.flows.Urls;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
-@ManagedBean(name = "url")
-@RequestScoped
public class UrlBean {
private URI baseURI;
- @ManagedProperty(value = "#{realm}")
private RealmBean realm;
- @ManagedProperty(value = "#{register}")
- private RegisterBean registerBean;
-
- @PostConstruct
- public void init() {
- FacesContext ctx = FacesContext.getCurrentInstance();
-
- HttpServletRequest request = (HttpServletRequest) ctx.getExternalContext().getRequest();
-
- UriBuilder b = UriBuilder.fromUri(request.getRequestURI()).replaceQuery(request.getQueryString())
- .replacePath(request.getContextPath()).path("rest");
-
- if (request.getAttribute(FormFlows.CODE) != null) {
- b.queryParam("code", request.getAttribute(FormFlows.CODE));
- }
-
- baseURI = b.build();
+ public UrlBean(RealmBean realm, URI baseURI){
+ this.realm = realm;
+ this.baseURI = baseURI;
}
public RealmBean getRealm() {
@@ -73,14 +47,6 @@ public class UrlBean {
this.realm = realm;
}
- public RegisterBean getRegisterBean() {
- return registerBean;
- }
-
- public void setRegisterBean(RegisterBean registerBean) {
- this.registerBean = registerBean;
- }
-
public String getAccessUrl() {
return Urls.accountAccessPage(baseURI, realm.getId()).toString();
}
@@ -115,10 +81,7 @@ public class UrlBean {
public String getRegistrationAction() {
if (realm.isSaas()) {
- // TODO: saas social registration
return Urls.saasRegisterAction(baseURI).toString();
- } else if (registerBean.isSocialRegistration()) {
- return Urls.socialRegisterAction(baseURI, realm.getId()).toString();
} else {
return Urls.realmRegisterAction(baseURI, realm.getId()).toString();
}
@@ -126,6 +89,7 @@ public class UrlBean {
public String getRegistrationUrl() {
if (realm.isSaas()) {
+ // TODO: saas social registration
return Urls.saasRegisterPage(baseURI).toString();
} else {
return Urls.realmRegisterPage(baseURI, realm.getId()).toString();
diff --git a/forms/src/main/java/org/keycloak/forms/UserBean.java b/forms/src/main/java/org/keycloak/forms/UserBean.java
index 0be17b3..97fe839 100644
--- a/forms/src/main/java/org/keycloak/forms/UserBean.java
+++ b/forms/src/main/java/org/keycloak/forms/UserBean.java
@@ -21,30 +21,17 @@
*/
package org.keycloak.forms;
-import javax.annotation.PostConstruct;
-import javax.faces.bean.ManagedBean;
-import javax.faces.bean.RequestScoped;
-import javax.faces.context.FacesContext;
-import javax.servlet.http.HttpServletRequest;
-
import org.keycloak.services.models.UserModel;
-import org.keycloak.services.resources.flows.FormFlows;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
-@ManagedBean(name = "user")
-@RequestScoped
public class UserBean {
private UserModel user;
- @PostConstruct
- public void init() {
- FacesContext ctx = FacesContext.getCurrentInstance();
- HttpServletRequest request = (HttpServletRequest) ctx.getExternalContext().getRequest();
-
- user = (UserModel) request.getAttribute(FormFlows.USER);
+ public UserBean(UserModel user){
+ this.user = user;
}
public String getFirstName() {
diff --git a/forms/src/main/java/org/keycloak/service/FormServiceImpl.java b/forms/src/main/java/org/keycloak/service/FormServiceImpl.java
new file mode 100644
index 0000000..41482ad
--- /dev/null
+++ b/forms/src/main/java/org/keycloak/service/FormServiceImpl.java
@@ -0,0 +1,250 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2012, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.keycloak.service;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.ResourceBundle;
+
+import freemarker.template.Configuration;
+import freemarker.template.Template;
+import freemarker.template.TemplateException;
+import org.jboss.resteasy.logging.Logger;
+import org.keycloak.forms.ErrorBean;
+import org.keycloak.forms.LoginBean;
+import org.keycloak.forms.RealmBean;
+import org.keycloak.forms.RegisterBean;
+import org.keycloak.forms.SocialBean;
+import org.keycloak.forms.TemplateBean;
+import org.keycloak.forms.TotpBean;
+import org.keycloak.forms.UrlBean;
+import org.keycloak.forms.UserBean;
+import org.keycloak.services.FormService;
+import org.keycloak.services.resources.flows.Pages;
+
+/**
+ * @author <a href="mailto:vrockai@redhat.com">Viliam Rockai</a>
+ */
+public class FormServiceImpl implements FormService {
+
+ private static final Logger log = Logger.getLogger(FormServiceImpl.class);
+
+ private static final String ID = "FormServiceId";
+ private static final String BUNDLE = "org.keycloak.forms.messages";
+ private final Map<String, Command> commandMap = new HashMap<String,Command>();
+
+ public FormServiceImpl(){
+ commandMap.put(Pages.LOGIN, new CommandLogin());
+ commandMap.put(Pages.REGISTER, new CommandRegister());
+ commandMap.put(Pages.ACCOUNT, new CommandAccount());
+ commandMap.put(Pages.PASSWORD, new CommandPassword());
+ commandMap.put(Pages.ACCESS, new CommandAccess());
+ commandMap.put(Pages.LOGIN_TOTP, new CommandLoginTotp());
+ commandMap.put(Pages.SECURITY_FAILURE, new CommandSecurityFailure());
+ commandMap.put(Pages.SOCIAL, new CommandSocial());
+ commandMap.put(Pages.TOTP, new CommandTotp());
+ commandMap.put(Pages.VERIFY_EMAIL, new CommandEmail());
+ }
+
+ public String getId(){
+ return ID;
+ }
+
+ public String process(String pageId, FormServiceDataBean dataBean){
+
+ Map<String, Object> attributes = new HashMap<String, Object>();
+
+ RealmBean realm = new RealmBean(dataBean.getRealm());
+ attributes.put("template", new TemplateBean(realm, dataBean.getContextPath()));
+
+ ResourceBundle rb = ResourceBundle.getBundle(BUNDLE);
+ attributes.put("rb", rb);
+
+ if (commandMap.containsKey(pageId)){
+ commandMap.get(pageId).exec(attributes, dataBean);
+ }
+
+ return processFmTemplate(pageId, attributes);
+ }
+
+ private String processFmTemplate(String temp, Map<String, Object> input) {
+
+ Writer out = new StringWriter();
+ Configuration cfg = new Configuration();
+
+ try {
+ cfg.setClassForTemplateLoading(FormServiceImpl.class,"/META-INF/resources");
+ Template template = cfg.getTemplate(temp);
+
+ template.process(input, out);
+ } catch (IOException e) {
+ log.error("Failed to load the template " + temp, e);
+ } catch (TemplateException e) {
+ log.error("Failed to process template " + temp, e);
+ }
+
+ return out.toString();
+ }
+
+ private class CommandTotp implements Command {
+ public void exec(Map<String, Object> attributes, FormServiceDataBean dataBean) {
+ RealmBean realm = new RealmBean(dataBean.getRealm());
+
+ attributes.put("realm", realm);
+ attributes.put("url", new UrlBean(realm, dataBean.getBaseURI()));
+
+ UserBean user = new UserBean(dataBean.getUserModel());
+ attributes.put("user", user);
+
+ TotpBean totp = new TotpBean(user, dataBean.getContextPath());
+ attributes.put("totp", totp);
+
+ attributes.put("login", new LoginBean(realm, dataBean.getFormData()));
+ }
+ }
+
+ private class CommandSocial implements Command {
+ public void exec(Map<String, Object> attributes, FormServiceDataBean dataBean) {
+ RealmBean realm = new RealmBean(dataBean.getRealm());
+
+ attributes.put("url", new UrlBean(realm, dataBean.getBaseURI()));
+ }
+ }
+
+ private class CommandEmail implements Command {
+ public void exec(Map<String, Object> attributes, FormServiceDataBean dataBean) {
+ }
+ }
+
+ private class CommandSecurityFailure implements Command {
+ public void exec(Map<String, Object> attributes, FormServiceDataBean dataBean) {
+ }
+ }
+
+ private class CommandPassword implements Command {
+ public void exec(Map<String, Object> attributes, FormServiceDataBean dataBean) {
+ RealmBean realm = new RealmBean(dataBean.getRealm());
+
+ attributes.put("realm", realm);
+ attributes.put("url", new UrlBean(realm, dataBean.getBaseURI()));
+ attributes.put("user", new UserBean(dataBean.getUserModel()));
+ attributes.put("login", new LoginBean(realm, dataBean.getFormData()));
+ }
+ }
+
+ private class CommandLoginTotp implements Command {
+ public void exec(Map<String, Object> attributes, FormServiceDataBean dataBean) {
+ if (dataBean.getError() != null){
+ attributes.put("error", new ErrorBean(dataBean.getError()));
+ }
+
+ RealmBean realm = new RealmBean(dataBean.getRealm());
+
+ attributes.put("realm", realm);
+
+ UrlBean url = new UrlBean(realm, dataBean.getBaseURI());
+
+ attributes.put("url", url);
+ attributes.put("user", new UserBean(dataBean.getUserModel()));
+ attributes.put("login", new LoginBean(realm, dataBean.getFormData()));
+
+ RegisterBean register = new RegisterBean(dataBean.getFormData(), dataBean.getSocialRegistration());
+
+ SocialBean social = new SocialBean(realm, register, url);
+ attributes.put("social", social);
+ }
+ }
+
+ private class CommandAccess implements Command {
+ public void exec(Map<String, Object> attributes, FormServiceDataBean dataBean) {
+ RealmBean realm = new RealmBean(dataBean.getRealm());
+
+ attributes.put("realm", realm);
+ attributes.put("url", new UrlBean(realm, dataBean.getBaseURI()));
+ }
+ }
+
+ private class CommandAccount implements Command {
+ public void exec(Map<String, Object> attributes, FormServiceDataBean dataBean) {
+ RealmBean realm = new RealmBean(dataBean.getRealm());
+
+ attributes.put("realm", realm);
+ attributes.put("url", new UrlBean(realm, dataBean.getBaseURI()));
+ attributes.put("user", new UserBean(dataBean.getUserModel()));
+ attributes.put("login", new LoginBean(realm, dataBean.getFormData()));
+ }
+ }
+
+ private class CommandLogin implements Command {
+ public void exec(Map<String, Object> attributes, FormServiceDataBean dataBean) {
+ if (dataBean.getError() != null){
+ attributes.put("error", new ErrorBean(dataBean.getError()));
+ }
+
+ RealmBean realm = new RealmBean(dataBean.getRealm());
+
+ attributes.put("realm", realm);
+
+ UrlBean url = new UrlBean(realm, dataBean.getBaseURI());
+
+ attributes.put("url", url);
+ attributes.put("user", new UserBean(dataBean.getUserModel()));
+ attributes.put("login", new LoginBean(realm, dataBean.getFormData()));
+
+ RegisterBean register = new RegisterBean(dataBean.getFormData(), dataBean.getSocialRegistration());
+
+ SocialBean social = new SocialBean(realm, register, url);
+ attributes.put("social", social);
+ }
+ }
+
+ private class CommandRegister implements Command {
+ public void exec(Map<String, Object> attributes, FormServiceDataBean dataBean) {
+ if (dataBean.getError() != null){
+ attributes.put("error", new ErrorBean(dataBean.getError()));
+ }
+
+ RealmBean realm = new RealmBean(dataBean.getRealm());
+
+ attributes.put("realm", realm);
+
+ UrlBean url = new UrlBean(realm, dataBean.getBaseURI());
+
+ attributes.put("url", url);
+ attributes.put("user", new UserBean(dataBean.getUserModel()));
+
+ RegisterBean register = new RegisterBean(dataBean.getFormData(), dataBean.getSocialRegistration());
+ attributes.put("register", register);
+
+ SocialBean social = new SocialBean(realm, register, url);
+ attributes.put("social", social);
+ }
+ }
+
+ private interface Command {
+ public void exec(Map<String, Object> attributes, FormServiceDataBean dataBean);
+ }
+
+}
\ No newline at end of file
diff --git a/forms/src/main/resources/META-INF/resources/forms/access.ftl b/forms/src/main/resources/META-INF/resources/forms/access.ftl
new file mode 100644
index 0000000..bcea82a
--- /dev/null
+++ b/forms/src/main/resources/META-INF/resources/forms/access.ftl
@@ -0,0 +1 @@
+<#include "./theme/" + template.theme + "/access.ftl">
\ No newline at end of file
diff --git a/forms/src/main/resources/META-INF/resources/forms/account.ftl b/forms/src/main/resources/META-INF/resources/forms/account.ftl
new file mode 100755
index 0000000..5c41000
--- /dev/null
+++ b/forms/src/main/resources/META-INF/resources/forms/account.ftl
@@ -0,0 +1 @@
+<#include "./theme/" + template.theme + "/account.ftl">
\ No newline at end of file
diff --git a/forms/src/main/resources/META-INF/resources/forms/error.ftl b/forms/src/main/resources/META-INF/resources/forms/error.ftl
new file mode 100644
index 0000000..3dd69c9
--- /dev/null
+++ b/forms/src/main/resources/META-INF/resources/forms/error.ftl
@@ -0,0 +1 @@
+template not found
\ No newline at end of file
diff --git a/forms/src/main/resources/META-INF/resources/forms/login.ftl b/forms/src/main/resources/META-INF/resources/forms/login.ftl
new file mode 100644
index 0000000..6033383
--- /dev/null
+++ b/forms/src/main/resources/META-INF/resources/forms/login.ftl
@@ -0,0 +1 @@
+<#include "./theme/" + template.theme + "/login.ftl">
\ No newline at end of file
diff --git a/forms/src/main/resources/META-INF/resources/forms/login-totp.ftl b/forms/src/main/resources/META-INF/resources/forms/login-totp.ftl
new file mode 100644
index 0000000..9bd8509
--- /dev/null
+++ b/forms/src/main/resources/META-INF/resources/forms/login-totp.ftl
@@ -0,0 +1 @@
+<#include "./theme/" + template.theme + "/login-totp.ftl">
\ No newline at end of file
diff --git a/forms/src/main/resources/META-INF/resources/forms/password.ftl b/forms/src/main/resources/META-INF/resources/forms/password.ftl
new file mode 100644
index 0000000..6fd1a4f
--- /dev/null
+++ b/forms/src/main/resources/META-INF/resources/forms/password.ftl
@@ -0,0 +1 @@
+<#include "./theme/" + template.theme + "/password.ftl">
\ No newline at end of file
diff --git a/forms/src/main/resources/META-INF/resources/forms/register.ftl b/forms/src/main/resources/META-INF/resources/forms/register.ftl
new file mode 100644
index 0000000..ff86d85
--- /dev/null
+++ b/forms/src/main/resources/META-INF/resources/forms/register.ftl
@@ -0,0 +1 @@
+<#include "./theme/" + template.theme + "/register.ftl">
\ No newline at end of file
diff --git a/forms/src/main/resources/META-INF/resources/forms/social.ftl b/forms/src/main/resources/META-INF/resources/forms/social.ftl
new file mode 100644
index 0000000..baf129e
--- /dev/null
+++ b/forms/src/main/resources/META-INF/resources/forms/social.ftl
@@ -0,0 +1 @@
+<#include "./theme/" + template.theme + "/social.ftl">
\ No newline at end of file
diff --git a/forms/src/main/resources/META-INF/resources/forms/theme/default/access.ftl b/forms/src/main/resources/META-INF/resources/forms/theme/default/access.ftl
new file mode 100755
index 0000000..a4b2413
--- /dev/null
+++ b/forms/src/main/resources/META-INF/resources/forms/theme/default/access.ftl
@@ -0,0 +1,11 @@
+<#import "template-main.ftl" as layout>
+<@layout.mainLayout ; section>
+
+ <#if section = "header">
+
+ Authorized Applications
+
+ <#elseif section = "content">
+
+ </#if>
+</@layout.mainLayout>
\ No newline at end of file
diff --git a/forms/src/main/resources/META-INF/resources/forms/theme/default/account.ftl b/forms/src/main/resources/META-INF/resources/forms/theme/default/account.ftl
new file mode 100755
index 0000000..252437b
--- /dev/null
+++ b/forms/src/main/resources/META-INF/resources/forms/theme/default/account.ftl
@@ -0,0 +1,33 @@
+<#import "template-main.ftl" as layout>
+<@layout.mainLayout ; section>
+
+ <#if section = "header">
+
+ Edit Account
+
+ <#elseif section = "content">
+
+ <form action="${url.accountUrl}" method="post">
+ <div>
+ <label for="firstName">${rb.getString('firstName')}</label>
+ <input type="text" id="firstName" name="firstName" value="${user.firstName?default('')}" />
+ </div>
+ <div>
+ <label for="lastName">${rb.getString('lastName')}</label>
+ <input type="text" id="lastName" name="lastName" value="${user.lastName?default('')}" />
+ </div>
+ <div>
+ <label for="email">${rb.getString('email')}</label>
+ <input type="text" id="email" name="email" value="${user.email?default('')}" />
+ </div>
+ <div>
+ <label for="username">${rb.getString('username')}</label>
+ <input type="text" id="username" name="username" value="${user.username?default('')}" disabled="true" />
+ </div>
+
+ <input type="button" value="Cancel" />
+ <input type="submit" value="Save" />
+ </form>
+
+ </#if>
+</@layout.mainLayout>
\ No newline at end of file
diff --git a/forms/src/main/resources/META-INF/resources/forms/theme/default/login.ftl b/forms/src/main/resources/META-INF/resources/forms/theme/default/login.ftl
new file mode 100755
index 0000000..80994d6
--- /dev/null
+++ b/forms/src/main/resources/META-INF/resources/forms/theme/default/login.ftl
@@ -0,0 +1,42 @@
+<#import "template-login.ftl" as layout>
+<@layout.registrationLayout bodyClass=""; section>
+ <#if section = "title">
+
+ Log in to ${realm.name}
+
+ <#elseif section = "header">
+
+ Log in to <strong>${(realm.name)?default('')}</strong>
+
+ <#elseif section = "form">
+
+ <div name="form">
+ <form action="${url.loginAction?default('')}" method="post">
+ <div>
+ <label for="username">${rb.getString('username')}</label>
+ <input id="username" name="username" value="${login.username?default('')}" type="text" />
+ </div>
+
+ <#list login.requiredCredentials as c>
+ <div>
+ <label for="${c.name}">${rb.getString(c.label)}</label> <input id="${c.name}" name="${c.name}" type="${c.inputType}" />
+ </div>
+ </#list>
+
+ <div class="aside-btn">
+ </div>
+
+ <input type="submit" value="Log In" />
+ </form>
+ </div>
+
+ <#elseif section = "info" >
+
+ <div name="info">
+ <#if realm.registrationAllowed>
+ <p>${rb.getString('noAccount')} <a href="${url.registrationUrl?default('')}">${rb.getString('register')}</a>.</p>
+ </#if>
+ </div>
+
+ </#if>
+</@layout.registrationLayout>
\ No newline at end of file
diff --git a/forms/src/main/resources/META-INF/resources/forms/theme/default/login-totp.ftl b/forms/src/main/resources/META-INF/resources/forms/theme/default/login-totp.ftl
new file mode 100755
index 0000000..5ca1109
--- /dev/null
+++ b/forms/src/main/resources/META-INF/resources/forms/theme/default/login-totp.ftl
@@ -0,0 +1,38 @@
+<#import "template-login.ftl" as layout>
+<@layout.registrationLayout bodyClass=""; section>
+
+ <#if section = "title">
+
+ Log in to ${realm.name}
+
+ <#elseif section = "header">
+
+ Log in to <strong>${realm.name}</strong>
+
+ <#elseif section = "form">
+
+ <form action="${url.loginAction}" method="post">
+ <input id="username" name="username" value="${login.username?default('')}" type="hidden" />
+ <input id="password" name="password" value="${login.password?default('')}" type="hidden" />
+
+ <div>
+ <label for="totp">${rb.getString('authenticatorCode')}</label>
+ <input id="totp" name="totp" type="text" />
+ </div>
+
+ <div class="aside-btn">
+ <!-- <input type="checkbox" id="remember" /><label for="remember">Remember Username</label> -->
+ <!-- <p>Forgot <a href="#">Username</a> or <a href="#">Password</a>?</p> -->
+ </div>
+
+ <input type="submit" value="Log In" />
+ </form>
+
+ <#elseif section = "info">
+
+ <#if realm.registrationAllowed>
+ <p>${rb.getString('noAccount')} <a href="${url.registrationUrl}">${rb.getString('register')}</a>.</p>
+ </#if>
+
+ </#if>
+</@layout.registrationLayout>
\ No newline at end of file
diff --git a/forms/src/main/resources/META-INF/resources/forms/theme/default/register.ftl b/forms/src/main/resources/META-INF/resources/forms/theme/default/register.ftl
new file mode 100755
index 0000000..a8f1eed
--- /dev/null
+++ b/forms/src/main/resources/META-INF/resources/forms/theme/default/register.ftl
@@ -0,0 +1,49 @@
+<#import "template-login.ftl" as layout>
+<@layout.registrationLayout bodyClass="register" ; section>
+
+ <#if section = "title">
+
+ ${rb.getString('registerWith')} ${realm.name}
+
+ <#elseif section = "header">
+
+ ${rb.getString('registerWith')} <strong>${realm.name}</strong>
+
+ <#elseif section = "form">
+
+ <form action="${url.registrationAction}" method="post">
+ <p class="subtitle">${rb.getString('allRequired')}</p>
+ <div>
+ <label for="name">${rb.getString('fullName')}</label>
+ <input type="text" id="name" name="name" value="${register.formData.name?default('')}" />
+ </div>
+ <div>
+ <label for="email">${rb.getString('email')}</label>
+ <input type="text" id="email" name="email" value="${register.formData.email?default('')}" />
+ </div>
+ <div>
+ <label for="username">${rb.getString('username')}</label>
+ <input type="text" id="username" name="username" value="${register.formData.username?default('')}" />
+ </div>
+ <div>
+ <label for="password">${rb.getString('password')}</label>
+ <input type="password" id="password" name="password" />
+ </div>
+ <div>
+ <label for="password-confirm">${rb.getString('passwordConfirm')}</label>
+ <input type="password" id="password-confirm" name="password-confirm" />
+ </div>
+
+ <div class="aside-btn">
+ <p>By registering you agree to the <a href="#">Terms of Service</a> and the <a href="#">Privacy Policy</a>.</p>
+ </div>
+
+ <input type="submit" value="Register" />
+ </form>
+
+ <#elseif section = "info">
+
+ <p>${rb.getString('alreadyHaveAccount')} <a href="${url.loginUrl}">${rb.getString('logIn')}</a>.</p>
+
+ </#if>
+</@layout.registrationLayout>
\ No newline at end of file
diff --git a/forms/src/main/resources/META-INF/resources/forms/theme/default/social.ftl b/forms/src/main/resources/META-INF/resources/forms/theme/default/social.ftl
new file mode 100755
index 0000000..97e51c4
--- /dev/null
+++ b/forms/src/main/resources/META-INF/resources/forms/theme/default/social.ftl
@@ -0,0 +1,12 @@
+<#import "template-main.ftl" as layout>
+<@layout.mainLayout ; section>
+
+ <#if section = "header">
+
+ Social Accounts
+
+ <#elseif section = "content">
+
+
+ </#if>
+</@layout.mainLayout>
\ No newline at end of file
diff --git a/forms/src/main/resources/META-INF/resources/forms/theme/default/totp.ftl b/forms/src/main/resources/META-INF/resources/forms/theme/default/totp.ftl
new file mode 100755
index 0000000..84c8da7
--- /dev/null
+++ b/forms/src/main/resources/META-INF/resources/forms/theme/default/totp.ftl
@@ -0,0 +1,38 @@
+<#import "template-main.ftl" as layout>
+<@layout.mainLayout ; section>
+
+ <#if section = "header">
+
+ Google Authenticator Setup
+
+ <#elseif section = "content">
+
+ <!--h:messages globalOnly="true" /-->
+ <#if totp.enabled>
+ Google Authenticator enabled
+ <#else>
+ <h2>To setup Google Authenticator</h2>
+
+ <ol>
+ <li>Install Google Authenticator to your device</li>
+ <li>Set up an account in Google Authenticator and scan the QR code below or enter the key<br />
+ <img src="${totp.totpSecretQrCodeUrl}" /> ${totp.totpSecretEncoded}
+ </li>
+ <li>Enter a one-time password provided by Google Authenticator and click Save to finish the setup
+
+ <form action="${url.totpUrl}" method="post">
+ <div>
+ <label for="totp">${rb.getString('authenticatorCode')}</label>
+ <input type="text" id="totp" name="totp" />
+ <input type="hidden" id="totpSecret" name="totpSecret" value="${totp.totpSecret}" />
+ </div>
+
+ <input type="button" value="Cancel" />
+ <input type="submit" value="Save" />
+ </form>
+ </li>
+ </ol>
+ </#if>
+
+ </#if>
+</@layout.mainLayout>
\ No newline at end of file
diff --git a/forms/src/main/resources/META-INF/resources/forms/totp.ftl b/forms/src/main/resources/META-INF/resources/forms/totp.ftl
new file mode 100644
index 0000000..ad15b2c
--- /dev/null
+++ b/forms/src/main/resources/META-INF/resources/forms/totp.ftl
@@ -0,0 +1 @@
+<#include "./theme/" + template.theme + "/totp.ftl">
\ No newline at end of file
diff --git a/forms/src/main/resources/META-INF/services/org.keycloak.services.FormService b/forms/src/main/resources/META-INF/services/org.keycloak.services.FormService
new file mode 100644
index 0000000..482f65d
--- /dev/null
+++ b/forms/src/main/resources/META-INF/services/org.keycloak.services.FormService
@@ -0,0 +1 @@
+org.keycloak.service.FormServiceImpl
\ No newline at end of file
pom.xml 5(+5 -0)
diff --git a/pom.xml b/pom.xml
index cfe307f..c4a3486 100755
--- a/pom.xml
+++ b/pom.xml
@@ -191,6 +191,11 @@
<artifactId>google-api-client</artifactId>
<version>1.14.1-beta</version>
</dependency>
+ <dependency>
+ <groupId>org.freemarker</groupId>
+ <artifactId>freemarker</artifactId>
+ <version>2.3.19</version>
+ </dependency>
<!-- Google+ -->
<dependency>
diff --git a/services/src/main/java/org/keycloak/services/FormService.java b/services/src/main/java/org/keycloak/services/FormService.java
new file mode 100644
index 0000000..8ddf517
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/FormService.java
@@ -0,0 +1,125 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2012, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.keycloak.services;
+
+import java.net.URI;
+
+import javax.ws.rs.core.MultivaluedMap;
+
+import org.keycloak.services.models.RealmModel;
+import org.keycloak.services.models.UserModel;
+
+/**
+ * @author <a href="mailto:vrockai@redhat.com">Viliam Rockai</a>
+ */
+public interface FormService {
+
+ String getId();
+
+ public String process(String pageId, FormServiceDataBean data);
+
+ public static class FormServiceDataBean {
+
+ private RealmModel realm;
+ private UserModel userModel;
+ private String error;
+ private MultivaluedMap<String, String> formData;
+ private URI baseURI;
+
+ public Boolean getSocialRegistration() {
+ return socialRegistration;
+ }
+
+ public void setSocialRegistration(Boolean socialRegistration) {
+ this.socialRegistration = socialRegistration;
+ }
+
+ private Boolean socialRegistration;
+
+ public String getCode() {
+ return code;
+ }
+
+ public void setCode(String code) {
+ this.code = code;
+ }
+
+ private String code;
+
+ public String getContextPath() {
+ return contextPath;
+ }
+
+ public void setContextPath(String contextPath) {
+ this.contextPath = contextPath;
+ }
+
+ private String contextPath;
+
+ public FormServiceDataBean(RealmModel realm, UserModel userModel, MultivaluedMap<String, String> formData, String error){
+ this.realm = realm;
+ this.userModel = userModel;
+ this.formData = formData;
+ this.error = error;
+ }
+
+ public URI getBaseURI() {
+ return baseURI;
+ }
+
+ public void setBaseURI(URI baseURI) {
+ this.baseURI = baseURI;
+ }
+
+ public String getError() {
+ return error;
+ }
+
+ public void setError(String error) {
+ this.error = error;
+ }
+
+ public MultivaluedMap<String, String> getFormData() {
+ return formData;
+ }
+
+ public void setFormData(MultivaluedMap<String, String> formData) {
+ this.formData = formData;
+ }
+
+ public RealmModel getRealm() {
+ return realm;
+ }
+
+ public RealmModel setRealm(RealmModel realm) {
+ return realm;
+ }
+
+ public UserModel getUserModel() {
+ return userModel;
+ }
+
+ public void setUserModel(UserModel userModel) {
+ this.userModel = userModel;
+ }
+ }
+}
diff --git a/services/src/main/java/org/keycloak/services/resources/flows/FormFlows.java b/services/src/main/java/org/keycloak/services/resources/flows/FormFlows.java
index 7b08e5c..c33be74 100755
--- a/services/src/main/java/org/keycloak/services/resources/flows/FormFlows.java
+++ b/services/src/main/java/org/keycloak/services/resources/flows/FormFlows.java
@@ -21,15 +21,22 @@
*/
package org.keycloak.services.resources.flows;
+import java.net.URI;
+import java.util.Iterator;
+
import org.jboss.resteasy.spi.HttpRequest;
+import org.jboss.resteasy.spi.ResteasyUriInfo;
+import org.keycloak.services.FormService;
import org.keycloak.services.email.EmailSender;
import org.keycloak.services.models.RealmModel;
import org.keycloak.services.models.UserModel;
import org.keycloak.services.models.UserModel.RequiredAction;
import org.picketlink.idm.model.sample.Realm;
+import javax.imageio.spi.ServiceRegistry;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
/**
@@ -85,29 +92,43 @@ public class FormFlows {
return forwardToForm(Pages.ACCOUNT);
}
- private Response forwardToForm(String form) {
- request.setAttribute(REALM, realm);
+ private Response forwardToForm(String template) {
- if (error != null) {
- request.setAttribute(ERROR_MESSAGE, error);
- }
+ FormService.FormServiceDataBean formDataBean = new FormService.FormServiceDataBean(realm, userModel, formData, error);
- if (formData != null) {
- request.setAttribute(DATA, formData);
- }
+ // Getting URI needed by form processing service
+ ResteasyUriInfo uriInfo = request.getUri();
+ MultivaluedMap<String, String> queryParameterMap = uriInfo.getQueryParameters();
+
+ String requestURI = uriInfo.getBaseUri().getPath();
+ UriBuilder uriBuilder = UriBuilder.fromUri(requestURI);
- if (userModel != null) {
- request.setAttribute(USER, userModel);
+ for(String k : queryParameterMap.keySet()){
+ uriBuilder.replaceQueryParam(k, queryParameterMap.get(k).toArray());
}
- if (code != null) {
- request.setAttribute(CODE, code);
+ if (code != null){
+ uriBuilder.queryParam(CODE, code);
}
- request.setAttribute(SOCIAL_REGISTRATION, socialRegistration);
+ URI baseURI = uriBuilder.build();
+ formDataBean.setBaseURI(baseURI);
+
+ // TODO find a better way to obtain contextPath
+ // Getting context path by removing "rest/" substring from the BaseUri path
+ formDataBean.setContextPath(requestURI.substring(0,requestURI.length()-5));
+ formDataBean.setSocialRegistration(socialRegistration);
+
+ // Find the service and process relevant template
+ Iterator<FormService> itr = ServiceRegistry.lookupProviders(FormService.class);
+
+ while (itr.hasNext()) {
+ FormService provider = itr.next();
+ if (provider.getId().equals("FormServiceId"))
+ return Response.status(200).entity(provider.process(template, formDataBean)).build();
+ }
- request.forward(form);
- return null;
+ return Response.status(200).entity("form provider not found").build();
}
public Response forwardToLogin() {
diff --git a/services/src/main/java/org/keycloak/services/resources/flows/Pages.java b/services/src/main/java/org/keycloak/services/resources/flows/Pages.java
index a1e770e..123b1dd 100644
--- a/services/src/main/java/org/keycloak/services/resources/flows/Pages.java
+++ b/services/src/main/java/org/keycloak/services/resources/flows/Pages.java
@@ -26,26 +26,26 @@ package org.keycloak.services.resources.flows;
*/
public class Pages {
- public final static String ACCESS = "/forms/access.xhtml";
+ public final static String ACCESS = "/forms/access.ftl";
- public final static String ACCOUNT = "/forms/account.xhtml";
+ public final static String ACCOUNT = "/forms/account.ftl";
- public final static String LOGIN = "/forms/login.xhtml";
+ public final static String LOGIN = "/forms/login.ftl";
- public final static String LOGIN_TOTP = "/forms/login-totp.xhtml";
+ public final static String LOGIN_TOTP = "/forms/login-totp.ftl";
public final static String OAUTH_GRANT = "/saas/oauthGrantForm.jsp";
- public final static String PASSWORD = "/forms/password.xhtml";
+ public final static String PASSWORD = "/forms/password.ftl";
- public final static String REGISTER = "/forms/register.xhtml";
+ public final static String REGISTER = "/forms/register.ftl";
public final static String SECURITY_FAILURE = "/saas/securityFailure.jsp";
- public final static String SOCIAL = "/forms/social.xhtml";
+ public final static String SOCIAL = "/forms/social.ftl";
- public final static String TOTP = "/forms/totp.xhtml";
+ public final static String TOTP = "/forms/totp.ftl";
- public final static String VERIFY_EMAIL = "/forms/verify-email.xhtml";
+ public final static String VERIFY_EMAIL = "/forms/verify-email.ftl";
}