[SYNCOPE-1041] SAML 2.0 SP extension: console components

Project: http://git-wip-us.apache.org/repos/asf/syncope/repo
Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/0ce5b4cd
Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/0ce5b4cd
Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/0ce5b4cd

Branch: refs/heads/2_0_X
Commit: 0ce5b4cdfa1f9f97dbbfd883d1afa9f996fd541d
Parents: d9079e1
Author: Francesco Chicchiriccò <[email protected]>
Authored: Tue Mar 21 14:20:30 2017 +0100
Committer: Francesco Chicchiriccò <[email protected]>
Committed: Fri Mar 31 15:25:11 2017 +0200

----------------------------------------------------------------------
 .../SyncopeConsoleRequestCycleListener.java     |  18 ++-
 .../client/console/SyncopeConsoleSession.java   |  40 +++++-
 .../client/console/commons/Constants.java       |   2 +
 .../client/console/commons/TemplateContent.java |  54 +++++++
 .../init/ClassPathScanImplementationLookup.java |  15 ++
 .../console/layout/ConsoleLayoutInfo.java       |  47 ++++++
 .../console/layout/ConsoleLayoutInfoModal.java  | 116 ---------------
 .../MailTemplateDirectoryPanel.java             |  58 ++++++--
 .../notifications/TemplateContentModal.java     | 126 ----------------
 .../syncope/client/console/pages/BasePage.java  |  29 +++-
 .../syncope/client/console/pages/Login.java     |  39 ++++-
 .../console/panels/RoleDirectoryPanel.java      |  32 ++++-
 .../console/panels/SSOLoginFormPanel.java       |  30 ++++
 .../console/panels/WorkflowTogglePanel.java     |  44 +++++-
 .../panels/XMLWorkflowEditorModalPanel.java     | 101 -------------
 .../reports/ReportTemplateDirectoryPanel.java   |  65 ++++++---
 .../client/console/tasks/CrontabPanel.java      |  17 +--
 .../markup/html/form/JsonEditorPanel.java       |  10 +-
 .../console/wizards/any/DynamicMemberships.java |   2 +-
 .../client/console/wizards/any/VirAttrs.java    |  22 ++-
 .../resources/META-INF/resources/css/login.css  | 143 +++++++++++--------
 .../SyncopeConsoleApplication.properties        |   7 +-
 .../SyncopeConsoleApplication_it.properties     |   6 +-
 .../SyncopeConsoleApplication_pt_BR.properties  |   6 +-
 .../SyncopeConsoleApplication_ru.properties     |   6 +-
 .../console/layout/ConsoleLayoutInfoModal.html  |  54 -------
 .../NotificationWizardBuilder$About.html        |  19 ++-
 .../notifications/TemplateContentModal.html     |  53 -------
 .../syncope/client/console/pages/Login.html     |   4 +
 .../panels/XMLWorkflowEditorModalPanel.html     |  53 -------
 .../console/panels/CamelRoutesDetailsPanel.java |  52 -------
 .../panels/CamelRoutesDirectoryPanel.java       |  98 ++++++-------
 .../console/panels/CamelRoutesModalPanel.java   |  46 ------
 .../console/panels/CamelRoutesDetailsPanel.html |  53 -------
 .../console/panels/CamelRoutesModalPanel.html   |  23 ---
 .../ext/saml2lsp/agent/AssertionConsumer.java   |   4 +-
 .../syncope/ext/saml2lsp/agent/Login.java       |   2 +-
 .../syncope/ext/saml2lsp/agent/Logout.java      |   4 +-
 ext/saml2sp/client-console/pom.xml              |  83 +++++++++++
 .../console/pages/SAML2SPBeforeLogout.java      |  37 +++++
 .../client/console/pages/SAML2SPLogin.java      |  70 +++++++++
 .../client/console/pages/SAML2SPLogout.java     |  39 +++++
 .../console/panels/SAMLSSOLoginFormPanel.java   | 107 ++++++++++++++
 .../console/panels/SAMLSSOLoginFormPanel.html   |  25 ++++
 .../syncope/common/lib/to/SAML2IdPTO.java       |  20 +++
 .../common/lib/to/SAML2LoginResponseTO.java     |  20 +++
 .../common/lib/types/SAML2SPEntitlement.java    |   2 -
 .../syncope/core/logic/AbstractSAML2Logic.java  |  35 +++++
 .../syncope/core/logic/SAML2IdPLogic.java       |  29 ++--
 .../apache/syncope/core/logic/SAML2SPLogic.java |  25 ++--
 .../syncope/core/logic/init/SAML2SPLoader.java  |  28 +++-
 .../core/logic/saml2/SAML2ReaderWriter.java     |  10 +-
 .../syncope/core/logic/saml2/SAML2Signer.java   |  10 +-
 .../core/persistence/api/entity/SAML2IdP.java   |   4 +
 .../persistence/jpa/entity/JPASAML2IdP.java     |  15 +-
 ext/saml2sp/pom.xml                             |   1 +
 .../java/data/SAML2IdPDataBinderImpl.java       |   2 +
 fit/console-reference/pom.xml                   |   2 +-
 .../src/main/webapp/WEB-INF/web.xml             |  22 ++-
 .../src/test/resources/rebel.xml                |   6 +
 60 files changed, 1138 insertions(+), 954 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/0ce5b4cd/client/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleRequestCycleListener.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleRequestCycleListener.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleRequestCycleListener.java
index e22266a..ac09333 100644
--- 
a/client/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleRequestCycleListener.java
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleRequestCycleListener.java
@@ -40,6 +40,14 @@ public class SyncopeConsoleRequestCycleListener extends 
AbstractRequestCycleList
 
     private static final Logger LOG = 
LoggerFactory.getLogger(SyncopeConsoleRequestCycleListener.class);
 
+    private static final String PAGE_EXPIRED = "Session expired: please login 
again";
+
+    private static final String MISSING_AUTHORIZATION = "Missing 
authorization";
+
+    private static final String MISSING_AUTHORIZATION_CORE = "Missing 
authorization while contacting Syncope core";
+
+    private static final String REST = "Error while contacting Syncope core";
+
     private Throwable instanceOf(final Exception e, final Class<? extends 
Exception> clazz) {
         return clazz.isAssignableFrom(e.getClass())
                 ? e
@@ -59,23 +67,23 @@ public class SyncopeConsoleRequestCycleListener extends 
AbstractRequestCycleList
 
         IRequestablePage errorPage = null;
         if (instanceOf(e, UnauthorizedInstantiationException.class) != null) {
-            errorParameters.add("errorMessage", 
"unauthorizedInstantiationException");
+            errorParameters.add("errorMessage", MISSING_AUTHORIZATION);
             errorPage = new Login(errorParameters);
         } else if (instanceOf(e, AccessControlException.class) != null) {
             if (instanceOf(e, 
AccessControlException.class).getMessage().contains("expired")) {
-                errorParameters.add("errorMessage", "pageExpiredException");
+                errorParameters.add("errorMessage", PAGE_EXPIRED);
             } else {
-                errorParameters.add("errorMessage", "accessControlException");
+                errorParameters.add("errorMessage", 
MISSING_AUTHORIZATION_CORE);
             }
             errorPage = new Login(errorParameters);
         } else if (instanceOf(e, PageExpiredException.class) != null || 
!SyncopeConsoleSession.get().isSignedIn()) {
-            errorParameters.add("errorMessage", "pageExpiredException");
+            errorParameters.add("errorMessage", PAGE_EXPIRED);
             errorPage = new Login(errorParameters);
         } else if (instanceOf(e, BadRequestException.class) != null
                 || instanceOf(e, WebServiceException.class) != null
                 || instanceOf(e, SyncopeClientException.class) != null) {
 
-            errorParameters.add("errorMessage", "restClientException");
+            errorParameters.add("errorMessage", REST);
             errorPage = new Login(errorParameters);
         } else {
             // redirect to default Wicket error page

http://git-wip-us.apache.org/repos/asf/syncope/blob/0ce5b4cd/client/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleSession.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleSession.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleSession.java
index 4bf0cd2..4064acf 100644
--- 
a/client/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleSession.java
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleSession.java
@@ -72,6 +72,8 @@ public class SyncopeConsoleSession extends 
AuthenticatedWebSession {
         THREAD_POOL_FACTORY.setDaemon(true);
     }
 
+    private final SyncopeClient anonymousClient;
+
     private final PlatformInfo platformInfo;
 
     private final SystemInfo systemInfo;
@@ -99,7 +101,7 @@ public class SyncopeConsoleSession extends 
AuthenticatedWebSession {
     public SyncopeConsoleSession(final Request request) {
         super(request);
 
-        SyncopeClient anonymousClient = 
SyncopeConsoleApplication.get().getClientFactory().
+        anonymousClient = SyncopeConsoleApplication.get().getClientFactory().
                 create(new AnonymousAuthenticationHandler(
                         SyncopeConsoleApplication.get().getAnonymousUser(),
                         SyncopeConsoleApplication.get().getAnonymousKey()));
@@ -113,6 +115,10 @@ public class SyncopeConsoleSession extends 
AuthenticatedWebSession {
                 EntityTOUtils.<DomainTO>keyTransformer(), domains);
     }
 
+    public SyncopeClient getAnonymousClient() {
+        return anonymousClient;
+    }
+
     public void execute(final Runnable command) {
         executorService.execute(command);
     }
@@ -141,6 +147,12 @@ public class SyncopeConsoleSession extends 
AuthenticatedWebSession {
         return client == null ? null : client.getJWT();
     }
 
+    private void afterAuthentication() {
+        Pair<Map<String, Set<String>>, UserTO> self = client.self();
+        auth = self.getKey();
+        selfTO = self.getValue();
+    }
+
     @Override
     public boolean authenticate(final String username, final String password) {
         boolean authenticated = false;
@@ -149,9 +161,7 @@ public class SyncopeConsoleSession extends 
AuthenticatedWebSession {
             client = SyncopeConsoleApplication.get().getClientFactory().
                     setDomain(getDomain()).create(username, password);
 
-            Pair<Map<String, Set<String>>, UserTO> self = client.self();
-            auth = self.getKey();
-            selfTO = self.getValue();
+            afterAuthentication();
 
             authenticated = true;
         } catch (Exception e) {
@@ -161,6 +171,28 @@ public class SyncopeConsoleSession extends 
AuthenticatedWebSession {
         return authenticated;
     }
 
+    public boolean authenticate(final String jwt) {
+        boolean authenticated = false;
+
+        try {
+            client = SyncopeConsoleApplication.get().getClientFactory().
+                    setDomain(getDomain()).create(jwt);
+
+            afterAuthentication();
+
+            authenticated = true;
+        } catch (Exception e) {
+            LOG.error("Authentication failed", e);
+        }
+
+        if (authenticated) {
+            bind();
+        }
+        signIn(authenticated);
+
+        return authenticated;
+    }
+
     public void cleanup() {
         client = null;
         auth = null;

http://git-wip-us.apache.org/repos/asf/syncope/blob/0ce5b4cd/client/console/src/main/java/org/apache/syncope/client/console/commons/Constants.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/commons/Constants.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/commons/Constants.java
index 70fb8ca..baf4653 100644
--- 
a/client/console/src/main/java/org/apache/syncope/client/console/commons/Constants.java
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/commons/Constants.java
@@ -47,6 +47,8 @@ public final class Constants {
 
     public static final String ERROR = "error";
 
+    public static final String BEFORE_LOGOUT_PAGE = "beforeLogoutPage";
+
     public static final String PARAM_PASSWORD_RESET_TOKEN = "pwdResetToken";
 
     public static final String PREF_USERS_DETAILS_VIEW = "users.details.view";

http://git-wip-us.apache.org/repos/asf/syncope/blob/0ce5b4cd/client/console/src/main/java/org/apache/syncope/client/console/commons/TemplateContent.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/commons/TemplateContent.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/commons/TemplateContent.java
new file mode 100644
index 0000000..402bfdd
--- /dev/null
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/commons/TemplateContent.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.commons;
+
+import java.io.Serializable;
+
+public class TemplateContent<F> implements Serializable {
+
+    private static final long serialVersionUID = 7772896797929614233L;
+
+    private final String key;
+
+    private String content;
+
+    private final F format;
+
+    public TemplateContent(final String key, final F format) {
+        this.key = key;
+        this.format = format;
+    }
+
+    public String getKey() {
+        return key;
+    }
+
+    public String getContent() {
+        return content;
+    }
+
+    public void setContent(final String content) {
+        this.content = content;
+    }
+
+    public F getFormat() {
+        return format;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/0ce5b4cd/client/console/src/main/java/org/apache/syncope/client/console/init/ClassPathScanImplementationLookup.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/init/ClassPathScanImplementationLookup.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/init/ClassPathScanImplementationLookup.java
index 1244075..d9ee460 100644
--- 
a/client/console/src/main/java/org/apache/syncope/client/console/init/ClassPathScanImplementationLookup.java
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/init/ClassPathScanImplementationLookup.java
@@ -30,6 +30,7 @@ import 
org.apache.syncope.client.console.annotations.BinaryPreview;
 import org.apache.syncope.client.console.annotations.ExtPage;
 import org.apache.syncope.client.console.annotations.ExtWidget;
 import org.apache.syncope.client.console.pages.BasePage;
+import org.apache.syncope.client.console.panels.SSOLoginFormPanel;
 import 
org.apache.syncope.client.console.wicket.markup.html.form.preview.AbstractBinaryPreviewer;
 import org.apache.syncope.client.console.widgets.BaseExtWidget;
 import org.slf4j.Logger;
@@ -53,6 +54,8 @@ public class ClassPathScanImplementationLookup {
 
     private List<Class<? extends BaseExtWidget>> extWidgets;
 
+    private List<Class<? extends SSOLoginFormPanel>> ssoLoginFormPanels;
+
     /**
      * This method can be overridden by subclasses to customize classpath scan.
      *
@@ -68,12 +71,14 @@ public class ClassPathScanImplementationLookup {
         previewers = new ArrayList<>();
         extPages = new ArrayList<>();
         extWidgets = new ArrayList<>();
+        ssoLoginFormPanels = new ArrayList<>();
 
         ClassPathScanningCandidateComponentProvider scanner = new 
ClassPathScanningCandidateComponentProvider(false);
         scanner.addIncludeFilter(new AssignableTypeFilter(BasePage.class));
         scanner.addIncludeFilter(new 
AssignableTypeFilter(AbstractBinaryPreviewer.class));
         scanner.addIncludeFilter(new AssignableTypeFilter(BaseExtPage.class));
         scanner.addIncludeFilter(new 
AssignableTypeFilter(BaseExtWidget.class));
+        scanner.addIncludeFilter(new 
AssignableTypeFilter(SSOLoginFormPanel.class));
 
         for (BeanDefinition bd : 
scanner.findCandidateComponents(getBasePackage())) {
             try {
@@ -100,6 +105,8 @@ public class ClassPathScanImplementationLookup {
                         pages.add((Class<? extends BasePage>) clazz);
                     } else if 
(AbstractBinaryPreviewer.class.isAssignableFrom(clazz)) {
                         previewers.add((Class<? extends 
AbstractBinaryPreviewer>) clazz);
+                    } else if 
(SSOLoginFormPanel.class.isAssignableFrom(clazz)) {
+                        ssoLoginFormPanels.add((Class<? extends 
SSOLoginFormPanel>) clazz);
                     }
                 }
             } catch (Throwable t) {
@@ -137,9 +144,12 @@ public class ClassPathScanImplementationLookup {
         });
         extWidgets = Collections.unmodifiableList(extWidgets);
 
+        ssoLoginFormPanels = Collections.unmodifiableList(ssoLoginFormPanels);
+
         LOG.debug("Binary previewers found: {}", previewers);
         LOG.debug("Extension pages found: {}", extPages);
         LOG.debug("Extension widgets found: {}", extWidgets);
+        LOG.debug("SSO Login pages found: {}", ssoLoginFormPanels);
     }
 
     public Class<? extends AbstractBinaryPreviewer> getPreviewerClass(final 
String mimeType) {
@@ -171,4 +181,9 @@ public class ClassPathScanImplementationLookup {
     public List<Class<? extends BaseExtWidget>> getExtWidgetClasses() {
         return extWidgets;
     }
+
+    public List<Class<? extends SSOLoginFormPanel>> getSSOLoginFormPanels() {
+        return ssoLoginFormPanels;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/0ce5b4cd/client/console/src/main/java/org/apache/syncope/client/console/layout/ConsoleLayoutInfo.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/layout/ConsoleLayoutInfo.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/layout/ConsoleLayoutInfo.java
new file mode 100644
index 0000000..c82eccd
--- /dev/null
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/layout/ConsoleLayoutInfo.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.layout;
+
+import java.io.Serializable;
+import org.apache.syncope.client.console.rest.AnyTypeRestClient;
+
+public class ConsoleLayoutInfo implements Serializable {
+
+    private static final long serialVersionUID = 961267717148831831L;
+
+    private final String key;
+
+    private String content;
+
+    public ConsoleLayoutInfo(final String key) {
+        this.key = key;
+    }
+
+    public String getKey() {
+        return key;
+    }
+
+    public String getContent() {
+        return content;
+    }
+
+    public void setContent(final String content) {
+        this.content = 
FormLayoutInfoUtils.defaultConsoleLayoutInfoIfEmpty(content, new 
AnyTypeRestClient().list());
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/0ce5b4cd/client/console/src/main/java/org/apache/syncope/client/console/layout/ConsoleLayoutInfoModal.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/layout/ConsoleLayoutInfoModal.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/layout/ConsoleLayoutInfoModal.java
deleted file mode 100644
index 4436dd9..0000000
--- 
a/client/console/src/main/java/org/apache/syncope/client/console/layout/ConsoleLayoutInfoModal.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.syncope.client.console.layout;
-
-import java.io.Serializable;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.syncope.client.console.SyncopeConsoleSession;
-import org.apache.syncope.client.console.commons.Constants;
-import org.apache.syncope.client.console.pages.BasePage;
-import org.apache.syncope.client.console.panels.AbstractModalPanel;
-import org.apache.syncope.client.console.rest.AnyTypeRestClient;
-import org.apache.syncope.client.console.rest.RoleRestClient;
-import 
org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
-import org.apache.wicket.PageReference;
-import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.markup.head.IHeaderResponse;
-import org.apache.wicket.markup.head.OnLoadHeaderItem;
-import org.apache.wicket.markup.html.form.Form;
-import org.apache.wicket.markup.html.form.TextArea;
-import org.apache.wicket.model.PropertyModel;
-
-public class ConsoleLayoutInfoModal extends AbstractModalPanel<Serializable> {
-
-    private static final long serialVersionUID = -5110368813584745668L;
-
-    private final ConsoleLayoutInfo consoleLayoutInfo;
-
-    public ConsoleLayoutInfoModal(
-            final BaseModal<Serializable> modal,
-            final ConsoleLayoutInfo consoleLayoutInfo,
-            final PageReference pageRef) {
-
-        super(modal, pageRef);
-        this.consoleLayoutInfo = consoleLayoutInfo;
-
-        TextArea<String> consoleLayoutInfoDefArea = new 
TextArea<>("consoleLayoutInfo", new PropertyModel<String>(
-                consoleLayoutInfo, "content"));
-        
consoleLayoutInfoDefArea.setMarkupId("consoleLayoutInfo").setOutputMarkupPlaceholderTag(true);
-        add(consoleLayoutInfoDefArea);
-    }
-
-    @Override
-    public void renderHead(final IHeaderResponse response) {
-        super.renderHead(response);
-        response.render(OnLoadHeaderItem.forScript(
-                
"CodeMirror.fromTextArea(document.getElementById('consoleLayoutInfo'), {"
-                + "  lineNumbers: true, "
-                + "  lineWrapping: true, "
-                + "  matchBrackets: true,"
-                + "  autoCloseBrackets: true,"
-                + "  autoRefresh: true"
-                + "}).on('change', updateTextArea);"));
-    }
-
-    @Override
-    public ConsoleLayoutInfo getItem() {
-        return consoleLayoutInfo;
-    }
-
-    @Override
-    public void onSubmit(final AjaxRequestTarget target, final Form<?> form) {
-        try {
-            new RoleRestClient().setConsoleLayoutInfo(
-                    consoleLayoutInfo.getKey(), 
consoleLayoutInfo.getContent());
-            
SyncopeConsoleSession.get().info(getString(Constants.OPERATION_SUCCEEDED));
-            modal.show(false);
-            modal.close(target);
-        } catch (Exception e) {
-            LOG.error("While updating onsole layout info for role {}", 
consoleLayoutInfo.getKey(), e);
-            
SyncopeConsoleSession.get().error(StringUtils.isBlank(e.getMessage()) ? 
e.getClass().getName() : e.
-                    getMessage());
-        }
-        ((BasePage) pageRef.getPage()).getNotificationPanel().refresh(target);
-    }
-
-    public static class ConsoleLayoutInfo implements Serializable {
-
-        private static final long serialVersionUID = 961267717148831831L;
-
-        private final String key;
-
-        private String content;
-
-        public ConsoleLayoutInfo(final String key) {
-            this.key = key;
-        }
-
-        public String getKey() {
-            return key;
-        }
-
-        public String getContent() {
-            return content;
-        }
-
-        public void setContent(final String content) {
-            this.content = 
FormLayoutInfoUtils.defaultConsoleLayoutInfoIfEmpty(content, new 
AnyTypeRestClient().list());
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/0ce5b4cd/client/console/src/main/java/org/apache/syncope/client/console/notifications/MailTemplateDirectoryPanel.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/notifications/MailTemplateDirectoryPanel.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/notifications/MailTemplateDirectoryPanel.java
index ba1bfd5..a9b16f1 100644
--- 
a/client/console/src/main/java/org/apache/syncope/client/console/notifications/MailTemplateDirectoryPanel.java
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/notifications/MailTemplateDirectoryPanel.java
@@ -19,7 +19,6 @@
 package org.apache.syncope.client.console.notifications;
 
 import de.agilecoders.wicket.core.markup.html.bootstrap.dialog.Modal;
-import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -27,6 +26,7 @@ import java.util.Iterator;
 import java.util.List;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.client.console.SyncopeConsoleSession;
+import org.apache.syncope.client.console.commons.TemplateContent;
 import org.apache.syncope.client.console.commons.Constants;
 import org.apache.syncope.client.console.commons.DirectoryDataProvider;
 import 
org.apache.syncope.client.console.commons.SortableDataProviderComparator;
@@ -55,14 +55,17 @@ import org.apache.wicket.model.IModel;
 import org.apache.wicket.model.ResourceModel;
 import org.apache.wicket.model.StringResourceModel;
 import org.apache.syncope.client.console.panels.WizardModalPanel;
+import 
org.apache.syncope.client.console.wicket.markup.html.form.XMLEditorPanel;
 import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.model.PropertyModel;
 
 public class MailTemplateDirectoryPanel
         extends DirectoryPanel<MailTemplateTO, MailTemplateTO, 
MailTemplateProvider, NotificationRestClient> {
 
     private static final long serialVersionUID = -3789392431954221446L;
 
-    protected final BaseModal<Serializable> utilityModal = new 
BaseModal<>("outer");
+    protected final BaseModal<String> utilityModal = new BaseModal<>("outer");
 
     public MailTemplateDirectoryPanel(final String id, final PageReference 
pageReference) {
         super(id, pageReference, true);
@@ -128,15 +131,13 @@ public class MailTemplateDirectoryPanel
 
                     @Override
                     public void onClick(final AjaxRequestTarget target, final 
MailTemplateTO ignore) {
-                        
TemplateContentModal.TemplateContent<MailTemplateFormat> content =
-                                new TemplateContentModal.TemplateContent<>(
-                                        model.getObject().getKey(), 
MailTemplateFormat.HTML);
+                        TemplateContent<MailTemplateFormat> content =
+                                new 
TemplateContent<>(model.getObject().getKey(), MailTemplateFormat.HTML);
                         content.setContent(
                                 
restClient.readTemplateFormat(model.getObject().getKey(), 
MailTemplateFormat.HTML));
 
                         utilityModal.header(new 
ResourceModel("mail.template.html", "HTML Content"));
-                        utilityModal.setContent(new TemplateContentModal<>(
-                                utilityModal, restClient, content, pageRef));
+                        utilityModal.setContent(new 
TemplateContentEditorPanel(content, pageRef));
                         utilityModal.show(true);
                         target.add(utilityModal);
                     }
@@ -148,16 +149,13 @@ public class MailTemplateDirectoryPanel
 
                     @Override
                     public void onClick(final AjaxRequestTarget target, final 
MailTemplateTO ignore) {
-                        
TemplateContentModal.TemplateContent<MailTemplateFormat> content =
-                                new TemplateContentModal.TemplateContent<>(
-                                        model.getObject().getKey(), 
MailTemplateFormat.TEXT);
+                        TemplateContent<MailTemplateFormat> content =
+                                new 
TemplateContent<>(model.getObject().getKey(), MailTemplateFormat.TEXT);
                         content.setContent(
                                 
restClient.readTemplateFormat(model.getObject().getKey(), 
MailTemplateFormat.TEXT));
 
-                        utilityModal.setFormModel(content);
                         utilityModal.header(new 
ResourceModel("mail.template.text", "TEXT Content"));
-                        utilityModal.setContent(new TemplateContentModal<>(
-                                utilityModal, restClient, content, pageRef));
+                        utilityModal.setContent(new 
TemplateContentEditorPanel(content, pageRef));
                         utilityModal.show(true);
                         target.add(utilityModal);
                     }
@@ -203,7 +201,7 @@ public class MailTemplateDirectoryPanel
         return Collections.<ActionLink.ActionType>emptyList();
     }
 
-    public class MailTemplateProvider extends 
DirectoryDataProvider<MailTemplateTO> {
+    protected final class MailTemplateProvider extends 
DirectoryDataProvider<MailTemplateTO> {
 
         private static final long serialVersionUID = -276043813563988590L;
 
@@ -240,4 +238,36 @@ public class MailTemplateDirectoryPanel
             };
         }
     }
+
+    private class TemplateContentEditorPanel extends XMLEditorPanel {
+
+        private static final long serialVersionUID = -3528875878627216097L;
+
+        private final TemplateContent<MailTemplateFormat> content;
+
+        TemplateContentEditorPanel(
+                final TemplateContent<MailTemplateFormat> content,
+                final PageReference pageRef) {
+
+            super(utilityModal, new PropertyModel<String>(content, "content"), 
false, pageRef);
+            this.content = content;
+        }
+
+        @Override
+        public void onSubmit(final AjaxRequestTarget target, final Form<?> 
form) {
+            try {
+                restClient.updateTemplateFormat(
+                        content.getKey(), content.getContent(), 
content.getFormat());
+                
SyncopeConsoleSession.get().info(getString(Constants.OPERATION_SUCCEEDED));
+                modal.show(false);
+                modal.close(target);
+            } catch (Exception e) {
+                LOG.error("While updating template for {}", content.getKey(), 
e);
+                
SyncopeConsoleSession.get().error(StringUtils.isBlank(e.getMessage())
+                        ? e.getClass().getName() : e.
+                        getMessage());
+            }
+            ((BasePage) 
pageRef.getPage()).getNotificationPanel().refresh(target);
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/0ce5b4cd/client/console/src/main/java/org/apache/syncope/client/console/notifications/TemplateContentModal.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/notifications/TemplateContentModal.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/notifications/TemplateContentModal.java
deleted file mode 100644
index f462388..0000000
--- 
a/client/console/src/main/java/org/apache/syncope/client/console/notifications/TemplateContentModal.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.syncope.client.console.notifications;
-
-import java.io.Serializable;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.syncope.client.console.SyncopeConsoleSession;
-import org.apache.syncope.client.console.commons.Constants;
-import org.apache.syncope.client.console.pages.BasePage;
-import org.apache.syncope.client.console.panels.AbstractModalPanel;
-import org.apache.syncope.client.console.rest.TemplateRestClient;
-import 
org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
-import org.apache.syncope.common.lib.to.EntityTO;
-import org.apache.wicket.PageReference;
-import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.markup.head.IHeaderResponse;
-import org.apache.wicket.markup.head.OnLoadHeaderItem;
-import org.apache.wicket.markup.html.form.Form;
-import org.apache.wicket.markup.html.form.TextArea;
-import org.apache.wicket.model.PropertyModel;
-
-public class TemplateContentModal<T extends EntityTO, F> extends 
AbstractModalPanel<Serializable> {
-
-    private static final long serialVersionUID = 2053048734388383021L;
-
-    private final TemplateContent<F> content;
-
-    private final TemplateRestClient<T, F> restClient;
-
-    public TemplateContentModal(
-            final BaseModal<Serializable> modal,
-            final TemplateRestClient<T, F> restClient,
-            final TemplateContent<F> content,
-            final PageReference pageRef) {
-
-        super(modal, pageRef);
-        this.restClient = restClient;
-        this.content = content;
-
-        TextArea<String> templateDefArea = new TextArea<>("template", new 
PropertyModel<String>(content, "content"));
-        
templateDefArea.setMarkupId("template").setOutputMarkupPlaceholderTag(true);
-        add(templateDefArea);
-    }
-
-    @Override
-    public void renderHead(final IHeaderResponse response) {
-        super.renderHead(response);
-        response.render(OnLoadHeaderItem.forScript(
-                "CodeMirror.fromTextArea(document.getElementById('template'), 
{"
-                + "  lineNumbers: true, "
-                + "  lineWrapping: true, "
-                + "  autoCloseTags: true, "
-                + "  mode: 'text/html', "
-                + "  autoRefresh: true"
-                + "}).on('change', updateTextArea);"));
-    }
-
-    @Override
-    public TemplateContent<F> getItem() {
-        return this.content;
-    }
-
-    @Override
-    public void onSubmit(final AjaxRequestTarget target, final Form<?> form) {
-        try {
-            restClient.updateTemplateFormat(
-                    content.getKey(), content.getContent(), 
content.getFormat());
-            
SyncopeConsoleSession.get().info(getString(Constants.OPERATION_SUCCEEDED));
-            modal.show(false);
-            modal.close(target);
-        } catch (Exception e) {
-            LOG.error("While updating template for {}", content.getKey(), e);
-            
SyncopeConsoleSession.get().error(StringUtils.isBlank(e.getMessage()) ? 
e.getClass().getName() : e.
-                    getMessage());
-        }
-        ((BasePage) pageRef.getPage()).getNotificationPanel().refresh(target);
-    }
-
-    public static class TemplateContent<F> implements Serializable {
-
-        private static final long serialVersionUID = -1756961687134322845L;
-
-        private final String key;
-
-        private String content;
-
-        private final F format;
-
-        public TemplateContent(final String key, final F format) {
-            this.key = key;
-            this.format = format;
-        }
-
-        public String getKey() {
-            return key;
-        }
-
-        public String getContent() {
-            return content;
-        }
-
-        public void setContent(final String content) {
-            this.content = content;
-        }
-
-        public F getFormat() {
-            return format;
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/0ce5b4cd/client/console/src/main/java/org/apache/syncope/client/console/pages/BasePage.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/pages/BasePage.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/pages/BasePage.java
index 0eaa5fc..ac74c77 100644
--- 
a/client/console/src/main/java/org/apache/syncope/client/console/pages/BasePage.java
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/pages/BasePage.java
@@ -41,6 +41,8 @@ import org.apache.wicket.Component;
 import org.apache.wicket.Page;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.ajax.IAjaxIndicatorAware;
+import org.apache.wicket.ajax.attributes.AjaxCallListener;
+import org.apache.wicket.ajax.attributes.AjaxRequestAttributes;
 import org.apache.wicket.ajax.markup.html.AjaxLink;
 import 
org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
 import org.apache.wicket.behavior.AttributeAppender;
@@ -238,7 +240,32 @@ public class BasePage extends WebPage implements 
IAjaxIndicatorAware {
             }
         });
         body.add(new Label("domain", SyncopeConsoleSession.get().getDomain()));
-        body.add(new BookmarkablePageLink<Page>("logout", Logout.class));
+
+        @SuppressWarnings("unchecked")
+        final Class<? extends WebPage> beforeLogout = (Class<? extends 
WebPage>) SyncopeConsoleSession.get().
+                getAttribute(Constants.BEFORE_LOGOUT_PAGE);
+        if (beforeLogout == null) {
+            body.add(new BookmarkablePageLink<Page>("logout", Logout.class));
+        } else {
+            body.add(new AjaxLink<Page>("logout") {
+
+                private static final long serialVersionUID = 
-7978723352517770644L;
+
+                @Override
+                protected void updateAjaxAttributes(final 
AjaxRequestAttributes attributes) {
+                    super.updateAjaxAttributes(attributes);
+
+                    AjaxCallListener ajaxCallListener = new AjaxCallListener();
+                    ajaxCallListener.onPrecondition("return confirm('" + 
getString("confirmGlobalLogout") + "');");
+                    attributes.getAjaxCallListeners().add(ajaxCallListener);
+                }
+
+                @Override
+                public void onClick(final AjaxRequestTarget target) {
+                    setResponsePage(beforeLogout);
+                }
+            });
+        }
 
         // set 'active' menu item for everything but extensions
         // 1. check if current class is set to top-level menu

http://git-wip-us.apache.org/repos/asf/syncope/blob/0ce5b4cd/client/console/src/main/java/org/apache/syncope/client/console/pages/Login.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/pages/Login.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/pages/Login.java
index 8f24e05..296576d 100644
--- 
a/client/console/src/main/java/org/apache/syncope/client/console/pages/Login.java
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/pages/Login.java
@@ -20,11 +20,16 @@ package org.apache.syncope.client.console.pages;
 
 import 
de.agilecoders.wicket.extensions.markup.html.bootstrap.form.select.BootstrapSelect;
 import java.security.AccessControlException;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Locale;
 import org.apache.syncope.client.console.SyncopeConsoleApplication;
 import org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.syncope.client.console.commons.Constants;
+import 
org.apache.syncope.client.console.init.ClassPathScanImplementationLookup;
+import org.apache.syncope.client.console.init.ConsoleInitializer;
 import org.apache.syncope.client.console.panels.NotificationPanel;
+import org.apache.syncope.client.console.panels.SSOLoginFormPanel;
 import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.ajax.markup.html.form.AjaxButton;
@@ -38,13 +43,19 @@ import org.apache.wicket.markup.html.form.Form;
 import org.apache.wicket.markup.html.form.PasswordTextField;
 import org.apache.wicket.markup.html.form.StatelessForm;
 import org.apache.wicket.markup.html.form.TextField;
+import org.apache.wicket.markup.html.list.ListItem;
+import org.apache.wicket.markup.html.list.ListView;
+import org.apache.wicket.markup.html.panel.Panel;
 import org.apache.wicket.model.IModel;
 import org.apache.wicket.model.Model;
-import org.apache.wicket.model.StringResourceModel;
 import org.apache.wicket.request.mapper.parameter.PageParameters;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public class Login extends WebPage {
 
+    private static final Logger LOG = LoggerFactory.getLogger(Login.class);
+
     private static final long serialVersionUID = 5889157642852559004L;
 
     private final NotificationPanel notificationPanel;
@@ -71,7 +82,7 @@ public class Login extends WebPage {
         exceptionMessage.setVisible(false);
         if (!parameters.get("errorMessage").isNull()) {
             exceptionMessage.setVisible(true);
-            exceptionMessage.setDefaultModel(new 
StringResourceModel(parameters.get("errorMessage").toString()));
+            
exceptionMessage.setDefaultModel(Model.of(parameters.get("errorMessage")));
         }
         add(exceptionMessage);
 
@@ -122,6 +133,30 @@ public class Login extends WebPage {
         form.add(submitButton);
         form.setDefaultButton(submitButton);
 
+        ClassPathScanImplementationLookup classPathScanImplementationLookup =
+                (ClassPathScanImplementationLookup) 
SyncopeConsoleApplication.get().
+                        
getServletContext().getAttribute(ConsoleInitializer.CLASSPATH_LOOKUP);
+        List<Panel> ssoLoginFormPanels = new ArrayList<>();
+        for (Class<? extends SSOLoginFormPanel> ssoLoginFormPanel : 
classPathScanImplementationLookup.
+                getSSOLoginFormPanels()) {
+
+            try {
+                
ssoLoginFormPanels.add(ssoLoginFormPanel.getConstructor(String.class).newInstance("ssoLogin"));
+            } catch (Exception e) {
+                LOG.error("Could not initialize the provided SSO login form 
panel", e);
+            }
+        }
+        ListView<Panel> ssoLogins = new ListView<Panel>("ssoLogins", 
ssoLoginFormPanels) {
+
+            private static final long serialVersionUID = -9180479401817023838L;
+
+            @Override
+            protected void populateItem(final ListItem<Panel> item) {
+                item.add(item.getModelObject());
+            }
+        };
+        form.add(ssoLogins);
+
         add(form);
     }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/0ce5b4cd/client/console/src/main/java/org/apache/syncope/client/console/panels/RoleDirectoryPanel.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/panels/RoleDirectoryPanel.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/panels/RoleDirectoryPanel.java
index 3292147..c7bd44b 100644
--- 
a/client/console/src/main/java/org/apache/syncope/client/console/panels/RoleDirectoryPanel.java
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/panels/RoleDirectoryPanel.java
@@ -18,7 +18,6 @@
  */
 package org.apache.syncope.client.console.panels;
 
-import org.apache.syncope.client.console.layout.ConsoleLayoutInfoModal;
 import de.agilecoders.wicket.core.markup.html.bootstrap.dialog.Modal;
 import java.io.Serializable;
 import java.util.ArrayList;
@@ -32,6 +31,7 @@ import 
org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.syncope.client.console.commons.Constants;
 import org.apache.syncope.client.console.commons.DirectoryDataProvider;
 import 
org.apache.syncope.client.console.commons.SortableDataProviderComparator;
+import org.apache.syncope.client.console.layout.ConsoleLayoutInfo;
 import org.apache.syncope.client.console.layout.FormLayoutInfoUtils;
 import org.apache.syncope.client.console.pages.BasePage;
 import 
org.apache.syncope.client.console.panels.RoleDirectoryPanel.RoleDataProvider;
@@ -43,6 +43,7 @@ import 
org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.Bas
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
 import 
org.apache.syncope.client.console.wicket.markup.html.form.ActionLink.ActionType;
 import 
org.apache.syncope.client.console.wicket.markup.html.form.ActionLinksPanel;
+import 
org.apache.syncope.client.console.wicket.markup.html.form.JsonEditorPanel;
 import org.apache.syncope.client.console.wizards.AjaxWizard;
 import org.apache.syncope.client.console.wizards.WizardMgtPanel;
 import org.apache.syncope.client.console.wizards.role.RoleWrapper;
@@ -60,9 +61,11 @@ import org.apache.wicket.event.Broadcast;
 import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
 import 
org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn;
 import org.apache.wicket.markup.html.WebPage;
+import org.apache.wicket.markup.html.form.Form;
 import org.apache.wicket.markup.html.panel.Panel;
 import org.apache.wicket.model.CompoundPropertyModel;
 import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.PropertyModel;
 import org.apache.wicket.model.ResourceModel;
 import org.apache.wicket.model.StringResourceModel;
 
@@ -70,7 +73,7 @@ public class RoleDirectoryPanel extends 
DirectoryPanel<RoleTO, RoleWrapper, Role
 
     private static final long serialVersionUID = -1100228004207271270L;
 
-    protected final BaseModal<Serializable> utilityModal = new 
BaseModal<>("outer");
+    protected final BaseModal<String> utilityModal = new BaseModal<>("outer");
 
     protected final BaseModal<Serializable> membersModal = new 
BaseModal<>("outer");
 
@@ -198,12 +201,31 @@ public class RoleDirectoryPanel extends 
DirectoryPanel<RoleTO, RoleWrapper, Role
 
                     @Override
                     public void onClick(final AjaxRequestTarget target, final 
RoleTO ignore) {
-                        ConsoleLayoutInfoModal.ConsoleLayoutInfo info = new 
ConsoleLayoutInfoModal.ConsoleLayoutInfo(
-                                model.getObject().getKey());
+                        final ConsoleLayoutInfo info = new 
ConsoleLayoutInfo(model.getObject().getKey());
                         
info.setContent(restClient.readConsoleLayoutInfo(model.getObject().getKey()));
 
                         utilityModal.header(new 
ResourceModel("console.layout.info", "JSON Content"));
-                        utilityModal.setContent(new 
ConsoleLayoutInfoModal(utilityModal, info, pageRef));
+                        utilityModal.setContent(new JsonEditorPanel(
+                                utilityModal, new PropertyModel<String>(info, 
"content"), false, pageRef) {
+
+                            private static final long serialVersionUID = 
-8927036362466990179L;
+
+                            @Override
+                            public void onSubmit(final AjaxRequestTarget 
target, final Form<?> form) {
+                                try {
+                                    
restClient.setConsoleLayoutInfo(info.getKey(), info.getContent());
+                                    
SyncopeConsoleSession.get().info(getString(Constants.OPERATION_SUCCEEDED));
+                                    modal.show(false);
+                                    modal.close(target);
+                                } catch (Exception e) {
+                                    LOG.error("While updating onsole layout 
info for role {}", info.getKey(), e);
+                                    
SyncopeConsoleSession.get().error(StringUtils.isBlank(e.getMessage())
+                                            ? e.getClass().getName() : e.
+                                            getMessage());
+                                }
+                                ((BasePage) 
pageRef.getPage()).getNotificationPanel().refresh(target);
+                            }
+                        });
                         utilityModal.show(true);
                         target.add(utilityModal);
                     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/0ce5b4cd/client/console/src/main/java/org/apache/syncope/client/console/panels/SSOLoginFormPanel.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/panels/SSOLoginFormPanel.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/panels/SSOLoginFormPanel.java
new file mode 100644
index 0000000..3bf6ac5
--- /dev/null
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/panels/SSOLoginFormPanel.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.panels;
+
+import org.apache.wicket.markup.html.panel.Panel;
+
+public abstract class SSOLoginFormPanel extends Panel {
+
+    private static final long serialVersionUID = -2371733568360773586L;
+
+    public SSOLoginFormPanel(final String id) {
+        super(id);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/0ce5b4cd/client/console/src/main/java/org/apache/syncope/client/console/panels/WorkflowTogglePanel.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/panels/WorkflowTogglePanel.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/panels/WorkflowTogglePanel.java
index 4a8ec34..be1553e 100644
--- 
a/client/console/src/main/java/org/apache/syncope/client/console/panels/WorkflowTogglePanel.java
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/panels/WorkflowTogglePanel.java
@@ -20,11 +20,19 @@ package org.apache.syncope.client.console.panels;
 
 import de.agilecoders.wicket.core.markup.html.bootstrap.dialog.Modal;
 import java.io.File;
+import java.io.IOException;
+import javax.ws.rs.core.MediaType;
+import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.client.console.SyncopeConsoleApplication;
+import org.apache.syncope.client.console.SyncopeConsoleSession;
+import org.apache.syncope.client.console.commons.Constants;
 import org.apache.syncope.client.console.pages.ActivitiModelerPopupPage;
+import org.apache.syncope.client.console.pages.BasePage;
 import org.apache.syncope.client.console.rest.WorkflowRestClient;
 import 
org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
+import 
org.apache.syncope.client.console.wicket.markup.html.form.XMLEditorPanel;
 import 
org.apache.syncope.client.console.wicket.markup.html.link.VeilPopupSettings;
+import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.types.StandardEntitlement;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.ajax.AjaxRequestTarget;
@@ -33,9 +41,13 @@ import 
org.apache.wicket.ajax.markup.html.form.AjaxSubmitLink;
 import 
org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
 import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
 import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.form.Form;
 import org.apache.wicket.markup.html.image.Image;
 import org.apache.wicket.markup.html.link.BookmarkablePageLink;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.Model;
 import org.apache.wicket.model.ResourceModel;
+import org.apache.wicket.util.io.IOUtils;
 
 public class WorkflowTogglePanel extends TogglePanel<String> {
 
@@ -88,9 +100,39 @@ public class WorkflowTogglePanel extends 
TogglePanel<String> {
 
             private static final long serialVersionUID = -1964967067512351526L;
 
+            private final WorkflowRestClient restClient = new 
WorkflowRestClient();
+
             @Override
             public void onClick(final AjaxRequestTarget target) {
-                target.add(modal.setContent(new 
XMLWorkflowEditorModalPanel(modal, new WorkflowRestClient(), pageRef)));
+                final IModel<String> wfDefinition = new Model<>();
+                try {
+                    
wfDefinition.setObject(IOUtils.toString(restClient.getDefinition(MediaType.APPLICATION_XML_TYPE)));
+                } catch (IOException e) {
+                    LOG.error("Could not get workflow definition", e);
+                }
+
+                target.add(modal.setContent(new XMLEditorPanel(modal, 
wfDefinition, false, pageRef) {
+
+                    private static final long serialVersionUID = 
5488080606102212554L;
+
+                    @Override
+                    public void onSubmit(final AjaxRequestTarget target, final 
Form<?> form) {
+                        if (StringUtils.isNotBlank(wfDefinition.getObject())) {
+                            try {
+                                
restClient.updateDefinition(MediaType.APPLICATION_XML_TYPE, 
wfDefinition.getObject());
+                                
SyncopeConsoleSession.get().info(getString(Constants.OPERATION_SUCCEEDED));
+
+                                modal.show(false);
+                                modal.close(target);
+                            } catch (SyncopeClientException e) {
+                                
SyncopeConsoleSession.get().error(StringUtils.isBlank(e.getMessage()) ? 
e.getClass().
+                                        getName() : e.
+                                                getMessage());
+                            }
+                            ((BasePage) 
pageRef.getPage()).getNotificationPanel().refresh(target);
+                        }
+                    }
+                }));
 
                 modal.header(new ResourceModel("xmlEditorTitle"));
                 modal.show(true);

http://git-wip-us.apache.org/repos/asf/syncope/blob/0ce5b4cd/client/console/src/main/java/org/apache/syncope/client/console/panels/XMLWorkflowEditorModalPanel.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/panels/XMLWorkflowEditorModalPanel.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/panels/XMLWorkflowEditorModalPanel.java
deleted file mode 100644
index b1eb97e..0000000
--- 
a/client/console/src/main/java/org/apache/syncope/client/console/panels/XMLWorkflowEditorModalPanel.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.syncope.client.console.panels;
-
-import java.io.IOException;
-import javax.ws.rs.core.MediaType;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.syncope.client.console.SyncopeConsoleSession;
-import org.apache.syncope.client.console.commons.Constants;
-import org.apache.syncope.client.console.pages.BasePage;
-import org.apache.syncope.client.console.rest.WorkflowRestClient;
-import 
org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
-import org.apache.syncope.common.lib.SyncopeClientException;
-import org.apache.wicket.PageReference;
-import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.markup.head.IHeaderResponse;
-import org.apache.wicket.markup.head.OnLoadHeaderItem;
-import org.apache.wicket.markup.html.form.Form;
-import org.apache.wicket.markup.html.form.TextArea;
-import org.apache.wicket.model.Model;
-import org.apache.wicket.util.io.IOUtils;
-
-public class XMLWorkflowEditorModalPanel extends AbstractModalPanel<String> {
-
-    private static final long serialVersionUID = 1937773326401753564L;
-
-    private final WorkflowRestClient wfRestClient;
-
-    private final TextArea<String> workflowDefArea;
-
-    private String wfDefinition;
-
-    public XMLWorkflowEditorModalPanel(
-            final BaseModal<String> modal,
-            final WorkflowRestClient wfRestClient,
-            final PageReference pageRef) {
-
-        super(modal, pageRef);
-        this.wfRestClient = wfRestClient;
-
-        try {
-            wfDefinition = 
IOUtils.toString(wfRestClient.getDefinition(MediaType.APPLICATION_XML_TYPE));
-        } catch (IOException e) {
-            LOG.error("Could not get workflow definition", e);
-            wfDefinition = StringUtils.EMPTY;
-        }
-
-        workflowDefArea = new TextArea<>("workflowDefArea", new 
Model<>(wfDefinition));
-        add(workflowDefArea);
-    }
-
-    @Override
-    public String getItem() {
-        return this.wfDefinition;
-    }
-
-    @Override
-    public void onSubmit(final AjaxRequestTarget target, final Form<?> form) {
-        try {
-            wfRestClient.updateDefinition(MediaType.APPLICATION_XML_TYPE, 
workflowDefArea.getModelObject());
-            
SyncopeConsoleSession.get().info(getString(Constants.OPERATION_SUCCEEDED));
-
-            modal.show(false);
-            modal.close(target);
-        } catch (SyncopeClientException e) {
-            
SyncopeConsoleSession.get().error(StringUtils.isBlank(e.getMessage()) ? 
e.getClass().getName() : e.
-                    getMessage());
-        }
-        ((BasePage) pageRef.getPage()).getNotificationPanel().refresh(target);
-    }
-
-    @Override
-    public void renderHead(final IHeaderResponse response) {
-        super.renderHead(response);
-        response.render(OnLoadHeaderItem.forScript(
-                
"CodeMirror.fromTextArea(document.getElementById('workflowDefArea'), {"
-                + "  lineNumbers: true, "
-                + "  lineWrapping: true, "
-                + "  autoCloseTags: true, "
-                + "  mode: 'text/html', "
-                + "  autoRefresh: true"
-                + "}).on('change', updateTextArea);"));
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/0ce5b4cd/client/console/src/main/java/org/apache/syncope/client/console/reports/ReportTemplateDirectoryPanel.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/reports/ReportTemplateDirectoryPanel.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/reports/ReportTemplateDirectoryPanel.java
index d89ac22..4b01fbd 100644
--- 
a/client/console/src/main/java/org/apache/syncope/client/console/reports/ReportTemplateDirectoryPanel.java
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/reports/ReportTemplateDirectoryPanel.java
@@ -19,7 +19,6 @@
 package org.apache.syncope.client.console.reports;
 
 import de.agilecoders.wicket.core.markup.html.bootstrap.dialog.Modal;
-import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -27,10 +26,10 @@ import java.util.Iterator;
 import java.util.List;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.client.console.SyncopeConsoleSession;
+import org.apache.syncope.client.console.commons.TemplateContent;
 import org.apache.syncope.client.console.commons.Constants;
 import org.apache.syncope.client.console.commons.DirectoryDataProvider;
 import 
org.apache.syncope.client.console.commons.SortableDataProviderComparator;
-import org.apache.syncope.client.console.notifications.TemplateContentModal;
 import org.apache.syncope.client.console.notifications.TemplateModal;
 import org.apache.syncope.client.console.pages.BasePage;
 import org.apache.syncope.client.console.panels.DirectoryPanel;
@@ -56,15 +55,18 @@ import org.apache.wicket.model.StringResourceModel;
 import org.apache.syncope.client.console.panels.WizardModalPanel;
 import 
org.apache.syncope.client.console.reports.ReportTemplateDirectoryPanel.ReportTemplateProvider;
 import org.apache.syncope.client.console.rest.ReportRestClient;
+import 
org.apache.syncope.client.console.wicket.markup.html.form.XMLEditorPanel;
 import org.apache.syncope.common.lib.types.ReportTemplateFormat;
 import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.model.PropertyModel;
 
 public class ReportTemplateDirectoryPanel
         extends DirectoryPanel<ReportTemplateTO, ReportTemplateTO, 
ReportTemplateProvider, ReportRestClient> {
 
     private static final long serialVersionUID = -3789392431954221446L;
 
-    protected final BaseModal<Serializable> utilityModal = new 
BaseModal<>("outer");
+    protected final BaseModal<String> utilityModal = new BaseModal<>("outer");
 
     public ReportTemplateDirectoryPanel(final String id, final PageReference 
pageReference) {
         super(id, pageReference, true);
@@ -130,15 +132,13 @@ public class ReportTemplateDirectoryPanel
 
                     @Override
                     public void onClick(final AjaxRequestTarget target, final 
ReportTemplateTO ignore) {
-                        
TemplateContentModal.TemplateContent<ReportTemplateFormat> content =
-                                new TemplateContentModal.TemplateContent<>(
-                                        model.getObject().getKey(), 
ReportTemplateFormat.FO);
+                        TemplateContent<ReportTemplateFormat> content =
+                                new 
TemplateContent<>(model.getObject().getKey(), ReportTemplateFormat.FO);
                         content.setContent(
                                 
restClient.readTemplateFormat(model.getObject().getKey(), 
ReportTemplateFormat.FO));
 
                         utilityModal.header(new 
ResourceModel("report.template.fo", "FO Content"));
-                        utilityModal.setContent(new TemplateContentModal<>(
-                                utilityModal, restClient, content, pageRef));
+                        utilityModal.setContent(new 
TemplateContentEditorPanel(content, pageRef));
                         utilityModal.show(true);
                         target.add(utilityModal);
                     }
@@ -150,14 +150,13 @@ public class ReportTemplateDirectoryPanel
 
                     @Override
                     public void onClick(final AjaxRequestTarget target, final 
ReportTemplateTO ignore) {
-                        
TemplateContentModal.TemplateContent<ReportTemplateFormat> content =
-                                new TemplateContentModal.TemplateContent<>(
-                                        model.getObject().getKey(), 
ReportTemplateFormat.HTML);
+                        TemplateContent<ReportTemplateFormat> content =
+                                new 
TemplateContent<>(model.getObject().getKey(), ReportTemplateFormat.HTML);
                         content.setContent(
                                 
restClient.readTemplateFormat(model.getObject().getKey(), 
ReportTemplateFormat.HTML));
 
                         utilityModal.header(new 
ResourceModel("report.template.html", "HTML Content"));
-                        utilityModal.setContent(new 
TemplateContentModal<>(utilityModal, restClient, content, pageRef));
+                        utilityModal.setContent(new 
TemplateContentEditorPanel(content, pageRef));
                         utilityModal.show(true);
                         target.add(utilityModal);
                     }
@@ -169,15 +168,13 @@ public class ReportTemplateDirectoryPanel
 
                     @Override
                     public void onClick(final AjaxRequestTarget target, final 
ReportTemplateTO ignore) {
-                        
TemplateContentModal.TemplateContent<ReportTemplateFormat> content =
-                                new TemplateContentModal.TemplateContent<>(
-                                        model.getObject().getKey(), 
ReportTemplateFormat.CSV);
+                        TemplateContent<ReportTemplateFormat> content =
+                                new 
TemplateContent<>(model.getObject().getKey(), ReportTemplateFormat.CSV);
                         content.setContent(
                                 
restClient.readTemplateFormat(model.getObject().getKey(), 
ReportTemplateFormat.CSV));
 
-                        utilityModal.setFormModel(content);
                         utilityModal.header(new 
ResourceModel("report.template.text", "TEXT Content"));
-                        utilityModal.setContent(new 
TemplateContentModal<>(utilityModal, restClient, content, pageRef));
+                        utilityModal.setContent(new 
TemplateContentEditorPanel(content, pageRef));
                         utilityModal.show(true);
                         target.add(utilityModal);
                     }
@@ -223,7 +220,7 @@ public class ReportTemplateDirectoryPanel
         return Collections.<ActionLink.ActionType>emptyList();
     }
 
-    public class ReportTemplateProvider extends 
DirectoryDataProvider<ReportTemplateTO> {
+    protected final class ReportTemplateProvider extends 
DirectoryDataProvider<ReportTemplateTO> {
 
         private static final long serialVersionUID = -276043813563988590L;
 
@@ -260,4 +257,36 @@ public class ReportTemplateDirectoryPanel
             };
         }
     }
+
+    private class TemplateContentEditorPanel extends XMLEditorPanel {
+
+        private static final long serialVersionUID = -3528875878627216097L;
+
+        private final TemplateContent<ReportTemplateFormat> content;
+
+        TemplateContentEditorPanel(
+                final TemplateContent<ReportTemplateFormat> content,
+                final PageReference pageRef) {
+
+            super(utilityModal, new PropertyModel<String>(content, "content"), 
false, pageRef);
+            this.content = content;
+        }
+
+        @Override
+        public void onSubmit(final AjaxRequestTarget target, final Form<?> 
form) {
+            try {
+                restClient.updateTemplateFormat(
+                        content.getKey(), content.getContent(), 
content.getFormat());
+                
SyncopeConsoleSession.get().info(getString(Constants.OPERATION_SUCCEEDED));
+                modal.show(false);
+                modal.close(target);
+            } catch (Exception e) {
+                LOG.error("While updating template for {}", content.getKey(), 
e);
+                
SyncopeConsoleSession.get().error(StringUtils.isBlank(e.getMessage())
+                        ? e.getClass().getName() : e.
+                        getMessage());
+            }
+            ((BasePage) 
pageRef.getPage()).getNotificationPanel().refresh(target);
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/0ce5b4cd/client/console/src/main/java/org/apache/syncope/client/console/tasks/CrontabPanel.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/tasks/CrontabPanel.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/tasks/CrontabPanel.java
index 451a71d..34b005c 100644
--- 
a/client/console/src/main/java/org/apache/syncope/client/console/tasks/CrontabPanel.java
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/tasks/CrontabPanel.java
@@ -100,28 +100,23 @@ public class CrontabPanel extends Panel {
         cronTemplateChooser.setChoiceRenderer(new 
SelectChoiceRenderer<SelectOption>());
         add(cronTemplateChooser);
 
-        seconds = new AjaxTextFieldPanel(
-                "seconds", "seconds", new 
Model<String>(getCronField(cronExpression, 0)));
+        seconds = new AjaxTextFieldPanel("seconds", "seconds", new 
Model<>(getCronField(cronExpression, 0)));
         add(seconds.hideLabel());
 
-        minutes = new AjaxTextFieldPanel(
-                "minutes", "minutes", new 
Model<String>(getCronField(cronExpression, 1)));
+        minutes = new AjaxTextFieldPanel("minutes", "minutes", new 
Model<>(getCronField(cronExpression, 1)));
         add(minutes.hideLabel());
 
-        hours = new AjaxTextFieldPanel(
-                "hours", "hours", new 
Model<String>(getCronField(cronExpression, 2)));
+        hours = new AjaxTextFieldPanel("hours", "hours", new 
Model<>(getCronField(cronExpression, 2)));
         add(hours.hideLabel());
 
         daysOfMonth = new AjaxTextFieldPanel(
-                "daysOfMonth", "daysOfMonth", new 
Model<String>(getCronField(cronExpression, 3)));
+                "daysOfMonth", "daysOfMonth", new 
Model<>(getCronField(cronExpression, 3)));
         add(daysOfMonth.hideLabel());
 
-        months = new AjaxTextFieldPanel(
-                "months", "months", new 
Model<String>(getCronField(cronExpression, 4)));
+        months = new AjaxTextFieldPanel("months", "months", new 
Model<>(getCronField(cronExpression, 4)));
         add(months.hideLabel());
 
-        daysOfWeek = new AjaxTextFieldPanel(
-                "daysOfWeek", "daysOfWeek", new 
Model<String>(getCronField(cronExpression, 5)));
+        daysOfWeek = new AjaxTextFieldPanel("daysOfWeek", "daysOfWeek", new 
Model<>(getCronField(cronExpression, 5)));
         add(daysOfWeek.hideLabel());
 
         final FormComponent<SelectOption> component = 
cronTemplateChooser.getField();

http://git-wip-us.apache.org/repos/asf/syncope/blob/0ce5b4cd/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/JsonEditorPanel.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/JsonEditorPanel.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/JsonEditorPanel.java
index 1f5a159..fb84c7e 100644
--- 
a/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/JsonEditorPanel.java
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/JsonEditorPanel.java
@@ -18,7 +18,6 @@
  */
 package org.apache.syncope.client.console.wicket.markup.html.form;
 
-import java.io.Serializable;
 import org.apache.syncope.client.console.panels.AbstractModalPanel;
 import 
org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
 import org.apache.wicket.PageReference;
@@ -27,7 +26,7 @@ import org.apache.wicket.markup.head.OnLoadHeaderItem;
 import org.apache.wicket.markup.html.form.TextArea;
 import org.apache.wicket.model.IModel;
 
-public class JsonEditorPanel extends AbstractModalPanel<Serializable> {
+public class JsonEditorPanel extends AbstractModalPanel<String> {
 
     private static final long serialVersionUID = -5110368813584745668L;
 
@@ -38,7 +37,7 @@ public class JsonEditorPanel extends 
AbstractModalPanel<Serializable> {
     }
 
     public JsonEditorPanel(
-            final BaseModal<Serializable> modal,
+            final BaseModal<String> modal,
             final IModel<String> content,
             final PageReference pageRef) {
         super(modal, pageRef);
@@ -60,9 +59,4 @@ public class JsonEditorPanel extends 
AbstractModalPanel<Serializable> {
                 + "  autoRefresh: true"
                 + "}).on('change', updateTextArea);"));
     }
-
-    @Override
-    public IModel<String> getItem() {
-        return content;
-    }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/0ce5b4cd/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/DynamicMemberships.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/DynamicMemberships.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/DynamicMemberships.java
index 5a6abe9..b061431 100644
--- 
a/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/DynamicMemberships.java
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/DynamicMemberships.java
@@ -90,7 +90,7 @@ public class DynamicMemberships extends WizardStep {
         // ------------------------
         add(new ListView<AnyTypeTO>("aDynMembershipCond", types) {
 
-            private static final long serialVersionUID = 1L;
+            private static final long serialVersionUID = 9101744072914090143L;
 
             @Override
             protected void populateItem(final ListItem<AnyTypeTO> item) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/0ce5b4cd/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/VirAttrs.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/VirAttrs.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/VirAttrs.java
index b3432f8..5a49b88 100644
--- 
a/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/VirAttrs.java
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/VirAttrs.java
@@ -74,24 +74,22 @@ public class VirAttrs extends AbstractAttrs<VirSchemaTO> {
 
         add(new ListView<MembershipTO>("membershipsVirSchemas", membershipTOs) 
{
 
-            private static final long serialVersionUID = 1L;
+            private static final long serialVersionUID = 9101744072914090143L;
 
             @Override
             protected void populateItem(final ListItem<MembershipTO> item) {
                 final MembershipTO membershipTO = item.getModelObject();
-                item.add(new Accordion("membershipVirSchemas", 
Collections.<ITab>singletonList(new AbstractTab(
-                        new StringResourceModel(
-                                "attributes.membership.accordion",
-                                VirAttrs.this,
-                                Model.of(membershipTO))) {
+                item.add(new Accordion("membershipVirSchemas",
+                        Collections.<ITab>singletonList(new AbstractTab(new 
StringResourceModel(
+                                "attributes.membership.accordion", 
VirAttrs.this, Model.of(membershipTO))) {
 
-                    private static final long serialVersionUID = 
1037272333056449378L;
+                            private static final long serialVersionUID = 
1037272333056449378L;
 
-                    @Override
-                    public WebMarkupContainer getPanel(final String panelId) {
-                        return new VirAttrs.VirSchemas(panelId, new 
ListModel<>(getAttrsFromTO(membershipTO)));
-                    }
-                }), Model.of(-1)).setOutputMarkupId(true));
+                            @Override
+                            public WebMarkupContainer getPanel(final String 
panelId) {
+                                return new VirAttrs.VirSchemas(panelId, new 
ListModel<>(getAttrsFromTO(membershipTO)));
+                            }
+                        }), Model.of(-1)).setOutputMarkupId(true));
             }
         });
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/0ce5b4cd/client/console/src/main/resources/META-INF/resources/css/login.css
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/META-INF/resources/css/login.css 
b/client/console/src/main/resources/META-INF/resources/css/login.css
index 768b4e5..575df66 100644
--- a/client/console/src/main/resources/META-INF/resources/css/login.css
+++ b/client/console/src/main/resources/META-INF/resources/css/login.css
@@ -17,107 +17,126 @@
  * under the License.
  */
 body, html {
-    height: 100% !important;
-    background-repeat: no-repeat;
-    background-image: linear-gradient(rgb(104, 145, 162), #00a65a);
+  height: 100% !important;
+  background-repeat: no-repeat;
+  background-image: linear-gradient(rgb(104, 145, 162), #00a65a);
 }
 
 .card-container.card {
-    width: 350px;
-    padding: 40px 40px;
+  width: 350px;
+  padding: 40px 40px;
 }
 
 .btn {
-    font-weight: 700;
-    height: 36px;
-    -moz-user-select: none;
-    -webkit-user-select: none;
-    user-select: none;
-    cursor: default;
+  font-weight: 700;
+  height: 36px;
+  -moz-user-select: none;
+  -webkit-user-select: none;
+  user-select: none;
+  cursor: default;
 }
 
 /*
  * Card component
  */
 .card {
-    background-color: #F7F7F7;
-    /* just in case there no content*/
-    padding: 20px 25px 30px;
-    margin: 0 auto 25px;
-    margin-top: 50px;
-    /* shadows and rounded borders */
-    -moz-border-radius: 2px;
-    -webkit-border-radius: 2px;
-    border-radius: 2px;
-    -moz-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
-    -webkit-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
-    box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
+  background-color: #F7F7F7;
+  /* just in case there no content*/
+  padding: 20px 25px 30px;
+  margin: 0 auto 25px;
+  margin-top: 50px;
+  /* shadows and rounded borders */
+  -moz-border-radius: 2px;
+  -webkit-border-radius: 2px;
+  border-radius: 2px;
+  -moz-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
+  -webkit-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
+  box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
 }
 
 .login-logo {
-    width: 200px;
-    margin: 0 auto 10px;
-    display: block;
+  width: 200px;
+  margin: 0 auto 10px;
+  display: block;
 }
 
 /*
  * Form styles
  */
 .profile-name-card {
-    font-size: 16px;
-    font-weight: bold;
-    text-align: center;
-    margin: 10px 0 0;
-    min-height: 1em;
+  font-size: 16px;
+  font-weight: bold;
+  text-align: center;
+  margin: 10px 0 0;
+  min-height: 1em;
 }
 
 .form-signin #inputPassword,
 .form-signin #inputPassword {
-    direction: ltr;
-    height: 44px;
-    font-size: 16px;
+  direction: ltr;
+  height: 44px;
+  font-size: 16px;
 }
 
 .form-signin input[type=password],
 .form-signin input[type=text],
 .form-signin button {
-    width: 100%;
-    display: block;
-    margin-bottom: 10px;
-    z-index: 1;
-    position: relative;
-    -moz-box-sizing: border-box;
-    -webkit-box-sizing: border-box;
-    box-sizing: border-box;
+  width: 100%;
+  display: block;
+  margin-bottom: 10px;
+  z-index: 1;
+  position: relative;
+  -moz-box-sizing: border-box;
+  -webkit-box-sizing: border-box;
+  box-sizing: border-box;
 }
 
 .form-signin .form-control:focus {
-    border-color: rgb(104, 145, 162);
-    outline: 0;
-    -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgb(104, 145, 
162);
-    box-shadow: inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgb(104, 145, 162);
+  border-color: rgb(104, 145, 162);
+  outline: 0;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgb(104, 145, 
162);
+  box-shadow: inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgb(104, 145, 162);
 }
 
 .btn.btn-signin {
-    /*background-color: #4d90fe; */
-    background-color: rgb(104, 145, 162);
-    /* background-color: linear-gradient(rgb(104, 145, 162), rgb(12, 97, 
33));*/
-    padding: 0px;
-    font-weight: 700;
-    font-size: 14px;
-    height: 36px;
-    -moz-border-radius: 3px;
-    -webkit-border-radius: 3px;
-    border-radius: 3px;
-    border: none;
-    -o-transition: all 0.218s;
-    -moz-transition: all 0.218s;
-    -webkit-transition: all 0.218s;
-    transition: all 0.218s;
+  background-color: rgb(104, 145, 162);
+  padding: 0px;
+  font-weight: 700;
+  font-size: 14px;
+  height: 36px;
+  -moz-border-radius: 3px;
+  -webkit-border-radius: 3px;
+  border-radius: 3px;
+  border: none;
+  -o-transition: all 0.218s;
+  -moz-transition: all 0.218s;
+  -webkit-transition: all 0.218s;
+  transition: all 0.218s;
 }
 
 .btn.btn-signin:hover,
 .btn.btn-signin:active,
 .btn.btn-signin:focus {
-    background-color: #00a65a;
+  background-color: #00a65a;
+}
+
+.btn.btn-sso {
+  padding: 0px;
+  font-weight: 700;
+  font-size: 14px;
+  height: 36px;
+  -moz-border-radius: 3px;
+  -webkit-border-radius: 3px;
+  border-radius: 3px;
+  border: none;
+  -o-transition: all 0.218s;
+  -moz-transition: all 0.218s;
+  -webkit-transition: all 0.218s;
+  transition: all 0.218s;
+}
+
+.btn.btn-sso:hover,
+.btn.btn-sso:active,
+.btn.btn-sso:focus {
+  background-color: #00a65a;
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/0ce5b4cd/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication.properties
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication.properties
 
b/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication.properties
index c8f42ad..77841d6 100644
--- 
a/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication.properties
+++ 
b/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication.properties
@@ -32,12 +32,6 @@ confirmUnassign=Do you really want to remove the assignment 
between the selected
 confirmDeprovision=Do you really want to de-provision the selected item(s)?
 confirmProvision=Do you really want to provision the selected item(s)?
 
-
-unauthorizedInstantiationException=Missing authorization.
-accessControlException=Missing authorization while contacting Syncope core.
-restClientException=Error while contacting Syncope core.
-pageExpiredException=Session expired: please login again.
-
 dropDownChoiceField.nullValid=Choose one
 DateTimeField$HoursValidator=Hour value must be in range (1, 12)
 error=Error
@@ -74,3 +68,4 @@ entitlements=Entitlements
 audit=Audit
 connectors.confirm.reload=This request is potentially dangerous for running 
operations, continue?
 intAttrNameInfo.help=Besides auto-completed attributes, you can also refer to 
groups, any objects or memberships  (if applicable); for example:
+confirmGlobalLogout=Do you really want to perform global logout?

http://git-wip-us.apache.org/repos/asf/syncope/blob/0ce5b4cd/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication_it.properties
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication_it.properties
 
b/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication_it.properties
index a17d3d8..8c2df2f 100644
--- 
a/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication_it.properties
+++ 
b/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication_it.properties
@@ -32,11 +32,6 @@ confirmUnassign=Vuoi davvero procedere rimuovendo 
l'assegnamento sulla risorsa?
 confirmDeprovision=Vuoi davvero procedere con il de-provisioning?
 confirmProvision=Vuoi davvero procedere con il provisioning?
 
-unauthorizedInstantiationException=Autorizzazione mancante.
-accessControlException=Autorizzazione mancante durante la comunicazione con 
Syncope core.
-restClientException=Errore durante la comunicazione con Syncope core.
-pageExpiredException=Sessione scaduta: eseguire di nuovo l'accesso.
-
 dropDownChoiceField.nullValid=Seleziona
 DateTimeField$HoursValidator=L'ora deve essere nell'intervallo (1,12)
 error=Errore
@@ -73,3 +68,4 @@ entitlements=Entitlement
 audit=Audit
 connectors.confirm.reload=Questa richiesta \u00e8 potenzialmente dannosa per 
le operazioni in corso, proseguire?
 intAttrNameInfo.help=Oltre agli attributi auto-completati, \u00e8 possibile 
fare riferimento anche a gruppi, any object e membership (se applicabile); ad 
esempio:
+confirmGlobalLogout=Vuoi davvero procedere al logout globale?

http://git-wip-us.apache.org/repos/asf/syncope/blob/0ce5b4cd/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication_pt_BR.properties
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication_pt_BR.properties
 
b/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication_pt_BR.properties
index b0abf0d..043df29 100644
--- 
a/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication_pt_BR.properties
+++ 
b/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication_pt_BR.properties
@@ -32,11 +32,6 @@ confirmUnassign=Voc\u00ea realmente deseja apagar a 
atribui\u00e7\u00e3o entre o
 confirmDeprovision=Voc\u00ea realmente de-provision item?
 confirmProvision=Voc\u00ea realmente provision item?
 
-unauthorizedInstantiationException=Falta de autoriza\u00e7\u00e3o para 
concluir.
-accessControlException=Falta de autoriza\u00e7\u00e3o ao comunicar-se com o 
Syncope core.
-restClientException=Erro ao comunicar-se com o Syncope core.
-pageExpiredException=Sess\u00e3o encerrada, favor logar-se novamente.
-
 dropDownChoiceField.nullValid=Escolha um
 DateTimeField$HoursValidator=O seu valor precisa estar entre (1, 12)
 error=Erro
@@ -73,3 +68,4 @@ entitlements=Entitlement
 audit=Audit
 connectors.confirm.reload=Esta requis\u00e7\u00e3o \u00e9 potencialmente 
perigosa para opera\u00e7\u00f5es em execu\u00e7\u00e3o, prosseguir?
 intAttrNameInfo.help=Besides auto-completed attributes, you can also refer to 
groups, any objects or memberships  (if applicable); for example:
+confirmGlobalLogout=Do you really want to perform global logout?

Reply via email to