[SYNCOPE-1435] New wicket enduser (#275)
diff --git a/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/BaseLogin.java b/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/BaseLogin.java
index f03f20a..44c4e23 100644
--- a/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/BaseLogin.java
+++ b/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/BaseLogin.java
@@ -63,6 +63,10 @@
protected static final Logger LOG = LoggerFactory.getLogger(BaseLogin.class);
+ public static final List<Locale> SUPPORTED_LOCALES = List.of(
+ Locale.ENGLISH, Locale.CANADA_FRENCH, Locale.ITALIAN, Locale.JAPANESE, new Locale("pt", "BR"),
+ new Locale("ru"));
+
@SpringBean
private DomainOps domainOps;
@@ -219,8 +223,6 @@
protected abstract String getAnonymousUser();
- protected abstract List<Locale> getSupportedLocales();
-
protected abstract void authenticate(
String username,
String password,
@@ -245,7 +247,7 @@
}
LocaleDropDown(final String id) {
- super(id, getSupportedLocales());
+ super(id, SUPPORTED_LOCALES);
setChoiceRenderer(new LocaleRenderer());
setModel(new IModel<Locale>() {
@@ -275,7 +277,7 @@
getHeader(HttpHeaders.ACCEPT_LANGUAGE);
if (StringUtils.isNotBlank(acceptLanguage)) {
try {
- filtered = Locale.filter(Locale.LanguageRange.parse(acceptLanguage), getSupportedLocales());
+ filtered = Locale.filter(Locale.LanguageRange.parse(acceptLanguage), SUPPORTED_LOCALES);
} catch (Exception e) {
LOG.debug("Could not parse {} HTTP header value '{}'",
HttpHeaders.ACCEPT_LANGUAGE, acceptLanguage, e);
diff --git a/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/Constants.java b/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/Constants.java
index ee8976a..2efdb0b 100644
--- a/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/Constants.java
+++ b/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/Constants.java
@@ -113,6 +113,8 @@
public static final int MAX_ROLE_LIST_SIZE = 30;
+ public static final String NOTIFICATION_TITLE_PARAM = "notificationTitle";
+
public static final String NOTIFICATION_MSG_PARAM = "notificationMessage";
public static final String NOTIFICATION_LEVEL_PARAM = "notificationLevel";
diff --git a/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/markup/html/form/AjaxPalettePanel.java b/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/markup/html/form/AjaxPalettePanel.java
index 339bea7..c6c2250 100644
--- a/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/markup/html/form/AjaxPalettePanel.java
+++ b/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/markup/html/form/AjaxPalettePanel.java
@@ -24,6 +24,7 @@
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.function.Function;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@@ -33,6 +34,7 @@
import org.apache.syncope.client.ui.commons.Constants;
import org.apache.syncope.client.ui.commons.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
import org.apache.syncope.client.ui.commons.pages.BaseWebPage;
+import org.apache.syncope.common.lib.to.UserTO;
import org.apache.wicket.Component;
import org.apache.wicket.Session;
import org.apache.wicket.ajax.AjaxRequestTarget;
@@ -193,6 +195,7 @@
@Override
protected void onUpdate(final AjaxRequestTarget target) {
processInput();
+ Optional.ofNullable(builder.event).ifPresent(e -> e.apply(target));
}
});
@@ -267,6 +270,8 @@
protected Function<String, Stream<String>> idExtractor =
(Function<String, Stream<String>> & Serializable) input -> Stream.of(Strings.split(input, ','));
+ protected Function<AjaxRequestTarget, Boolean> event;
+
protected Function<Object, Map<String, String>> additionalAttributes;
public Builder<T> setName(final String name) {
@@ -320,6 +325,11 @@
return this;
}
+ public Builder<T> event(final Function<AjaxRequestTarget, Boolean> event) {
+ this.event = event;
+ return this;
+ }
+
public Builder<T> additionalAttributes(final Function<Object, Map<String, String>> additionalAttributes) {
this.additionalAttributes = additionalAttributes;
return this;
@@ -404,4 +414,24 @@
return filtered;
}
}
+
+ public static class UpdateActionEvent {
+
+ private final UserTO item;
+
+ private final AjaxRequestTarget target;
+
+ public UpdateActionEvent(final UserTO item, final AjaxRequestTarget target) {
+ this.item = item;
+ this.target = target;
+ }
+
+ public UserTO getItem() {
+ return item;
+ }
+
+ public AjaxRequestTarget getTarget() {
+ return target;
+ }
+ }
}
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/BinaryFieldDownload.java b/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/markup/html/form/BinaryFieldDownload.java
similarity index 97%
rename from client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/BinaryFieldDownload.java
rename to client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/markup/html/form/BinaryFieldDownload.java
index 65b0c03..d64f997 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/BinaryFieldDownload.java
+++ b/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/markup/html/form/BinaryFieldDownload.java
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.syncope.client.console.wicket.markup.html.form;
+package org.apache.syncope.client.ui.commons.markup.html.form;
import java.time.Duration;
import org.apache.commons.lang3.StringUtils;
diff --git a/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/panels/CardPanel.java b/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/panels/CardPanel.java
new file mode 100644
index 0000000..face722
--- /dev/null
+++ b/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/panels/CardPanel.java
@@ -0,0 +1,66 @@
+/*
+ * 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.ui.commons.panels;
+
+import org.apache.wicket.Component;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.ResourceModel;
+
+public final class CardPanel<T extends Component> extends Panel {
+
+ private static final long serialVersionUID = -7906010415162945394L;
+
+ private CardPanel(final String id, final Builder<T> builder) {
+ super(id);
+ this.setOutputMarkupId(true);
+ this.setVisible(builder.visible);
+
+ this.add(new Label("cardLabel", new ResourceModel(builder.name, builder.name)).setOutputMarkupId(true));
+ this.add(builder.component);
+ }
+
+ public static class Builder<T extends Component> {
+
+ protected String name;
+
+ protected T component;
+
+ protected boolean visible;
+
+ public Builder<T> setName(final String name) {
+ this.name = name;
+ return this;
+ }
+
+ public Builder<T> setComponent(final T component) {
+ this.component = component;
+ return this;
+ }
+
+ public Builder<T> isVisible(final boolean visible) {
+ this.visible = visible;
+ return this;
+ }
+
+ public CardPanel<T> build(final String id) {
+ return new CardPanel<>(id, this);
+ }
+ }
+}
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/themes/AdminLTE.java b/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/themes/AdminLTE.java
similarity index 96%
rename from client/idrepo/console/src/main/java/org/apache/syncope/client/console/themes/AdminLTE.java
rename to client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/themes/AdminLTE.java
index d270149..1dccc49 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/themes/AdminLTE.java
+++ b/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/themes/AdminLTE.java
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.syncope.client.console.themes;
+package org.apache.syncope.client.ui.commons.themes;
import de.agilecoders.wicket.core.settings.Theme;
import java.util.ArrayList;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/themes/AdminLTECssResourceReference.java b/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/themes/AdminLTECssResourceReference.java
similarity index 96%
rename from client/idrepo/console/src/main/java/org/apache/syncope/client/console/themes/AdminLTECssResourceReference.java
rename to client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/themes/AdminLTECssResourceReference.java
index 397ef5e..f9e3617 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/themes/AdminLTECssResourceReference.java
+++ b/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/themes/AdminLTECssResourceReference.java
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.syncope.client.console.themes;
+package org.apache.syncope.client.ui.commons.themes;
import de.agilecoders.wicket.core.Bootstrap;
import java.util.ArrayList;
diff --git a/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/wizards/any/PasswordPanel.java b/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/wizards/any/PasswordPanel.java
index 6cf3087..d34ef77 100644
--- a/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/wizards/any/PasswordPanel.java
+++ b/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/wizards/any/PasswordPanel.java
@@ -38,14 +38,16 @@
public PasswordPanel(
final String id,
final UserWrapper wrapper,
+ final Boolean storePasswordInSyncope,
final boolean templateMode) {
- this(id, wrapper, templateMode, null);
+ this(id, wrapper, templateMode, storePasswordInSyncope, null);
}
public PasswordPanel(
final String id,
final UserWrapper wrapper,
final boolean templateMode,
+ final Boolean storePasswordInSyncope,
final PasswordStrengthBehavior passwordStrengthBehavior) {
super(id);
@@ -88,16 +90,16 @@
form.add(new EqualPasswordInputValidator(passwordField.getField(), confirmPasswordField.getField()));
}
- AjaxCheckBoxPanel storePasswordInSyncope = new AjaxCheckBoxPanel("storePasswordInSyncope",
+ AjaxCheckBoxPanel storePasswordInSyncopePanel = new AjaxCheckBoxPanel("storePasswordInSyncope",
"storePasswordInSyncope", new PropertyModel<>(wrapper, "storePasswordInSyncope"));
- storePasswordInSyncope.getField().setLabel(new ResourceModel("storePasswordInSyncope"));
- storePasswordInSyncope.setOutputMarkupId(true);
- storePasswordInSyncope.setOutputMarkupPlaceholderTag(true);
- if (wrapper.getInnerObject().getKey() == null) {
- storePasswordInSyncope.getField().setDefaultModelObject(Boolean.TRUE);
+ storePasswordInSyncopePanel.getField().setLabel(new ResourceModel("storePasswordInSyncope"));
+ storePasswordInSyncopePanel.setOutputMarkupId(true);
+ storePasswordInSyncopePanel.setOutputMarkupPlaceholderTag(true);
+ if (storePasswordInSyncope) {
+ storePasswordInSyncopePanel.getField().setDefaultModelObject(Boolean.TRUE);
} else {
- storePasswordInSyncope.setVisible(false);
+ storePasswordInSyncopePanel.setVisible(false);
}
- form.add(storePasswordInSyncope);
+ form.add(storePasswordInSyncopePanel);
}
}
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/UserDetails$EditUserPasswordPanel.html b/client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/panels/CardPanel.html
similarity index 73%
copy from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/UserDetails$EditUserPasswordPanel.html
copy to client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/panels/CardPanel.html
index e77ed5d..1ef8d64 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/UserDetails$EditUserPasswordPanel.html
+++ b/client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/panels/CardPanel.html
@@ -1,3 +1,4 @@
+<?xml version="1.0" encoding="UTF-8" ?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
@@ -18,12 +19,13 @@
-->
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
<wicket:panel>
- <div id="editUserChangePassword">
- <div class="alert alert-warning">
- <i class="fas fa-exclamation-triangle"></i> <label wicket:id="warning">[warning]</label>
+ <div class="box-header formcard">
+ <header class="card-container card-red">
+ <label class="card-header-style" wicket:id="cardLabel">[CARD LABEL]</label>
+ </header>
+ <div class="card-container-body">
+ <span wicket:id="contentPanel">[CONTENT PANEL]</span>
</div>
-
- <div wicket:id="passwordPanel">[change password panel]</div>
</div>
</wicket:panel>
</html>
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/themes/css/AdminLTE.css b/client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/themes/css/AdminLTE.css
similarity index 100%
rename from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/themes/css/AdminLTE.css
rename to client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/themes/css/AdminLTE.css
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/themes/js/AdminLTE-app.min.js b/client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/themes/js/AdminLTE-app.min.js
similarity index 100%
rename from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/themes/js/AdminLTE-app.min.js
rename to client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/themes/js/AdminLTE-app.min.js
diff --git a/client/idrepo/console/pom.xml b/client/idrepo/console/pom.xml
index db78158..dc4ca1a 100644
--- a/client/idrepo/console/pom.xml
+++ b/client/idrepo/console/pom.xml
@@ -123,7 +123,6 @@
<artifactId>disruptor</artifactId>
</dependency>
- <!-- required by wicket tester -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/SyncopeWebApplication.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/SyncopeWebApplication.java
index 76ff69c..a9e48da 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/SyncopeWebApplication.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/SyncopeWebApplication.java
@@ -28,8 +28,6 @@
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import org.apache.commons.lang3.BooleanUtils;
@@ -43,7 +41,6 @@
import org.apache.syncope.client.console.pages.BasePage;
import org.apache.syncope.client.console.pages.Dashboard;
import org.apache.syncope.client.console.pages.Login;
-import org.apache.syncope.client.console.themes.AdminLTE;
import org.apache.syncope.client.lib.SyncopeClientFactoryBean;
import org.apache.syncope.common.lib.PropertyUtils;
import org.apache.wicket.Page;
@@ -69,6 +66,7 @@
import org.apache.syncope.client.console.commons.VirSchemaDetailsPanelProvider;
import org.apache.syncope.client.console.pages.MustChangePassword;
import org.apache.syncope.client.console.panels.AnyPanel;
+import org.apache.syncope.client.ui.commons.themes.AdminLTE;
import org.apache.syncope.client.ui.commons.SyncopeUIRequestCycleListener;
import org.apache.syncope.client.ui.commons.Constants;
import org.apache.syncope.common.keymaster.client.api.model.NetworkService;
@@ -88,10 +86,6 @@
private static final String CONSOLE_PROPERTIES = "console.properties";
- public static final List<Locale> SUPPORTED_LOCALES = List.of(
- Locale.ENGLISH, Locale.CANADA_FRENCH, Locale.ITALIAN, Locale.JAPANESE, new Locale("pt", "BR"),
- new Locale("ru"));
-
public static SyncopeWebApplication get() {
return (SyncopeWebApplication) WebApplication.get();
}
@@ -169,7 +163,7 @@
}
}
- protected void setSecurityHeaders(final Properties props, final WebResponse response) {
+ protected static void setSecurityHeaders(final Properties props, final WebResponse response) {
@SuppressWarnings("unchecked")
Enumeration<String> propNames = (Enumeration<String>) props.propertyNames();
while (propNames.hasMoreElements()) {
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/BasePage.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/BasePage.java
index 11a1cad..a6ff75f 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/BasePage.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/BasePage.java
@@ -22,6 +22,7 @@
import java.lang.reflect.Constructor;
import java.time.Duration;
import java.util.List;
+import java.util.stream.StreamSupport;
import org.apache.commons.lang3.StringUtils;
import org.apache.syncope.client.console.BookmarkablePageLinkBuilder;
import org.apache.syncope.client.console.SyncopeConsoleSession;
@@ -394,19 +395,16 @@
}
// 4. when found, set CSS coordinates for menu
if (containingLI != null) {
- for (Component child : containingLI) {
- if (child instanceof Link) {
- child.add(new Behavior() {
+ StreamSupport.stream(containingLI.spliterator(), false).filter(Link.class::isInstance).
+ forEach(child -> child.add(new Behavior() {
- private static final long serialVersionUID = -5775607340182293596L;
+ private static final long serialVersionUID = -5775607340182293596L;
- @Override
- public void onComponentTag(final Component component, final ComponentTag tag) {
- tag.append("class", "active", " ");
- }
- });
+ @Override
+ public void onComponentTag(final Component component, final ComponentTag tag) {
+ tag.append("class", "active", " ");
}
- }
+ }));
if (keymasterULContainer.getId().equals(containingLI.getParent().getId())) {
keymasterULContainer.add(new Behavior() {
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/Login.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/Login.java
index 37944e8..a1244fe 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/Login.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/Login.java
@@ -21,7 +21,6 @@
import java.security.AccessControlException;
import java.util.ArrayList;
import java.util.List;
-import java.util.Locale;
import org.apache.syncope.client.console.SyncopeWebApplication;
import org.apache.syncope.client.console.SyncopeConsoleSession;
import org.apache.syncope.client.ui.commons.BaseLogin;
@@ -71,11 +70,6 @@
}
@Override
- protected List<Locale> getSupportedLocales() {
- return SyncopeWebApplication.SUPPORTED_LOCALES;
- }
-
- @Override
protected void authenticate(final String username, final String password, final AjaxRequestTarget target)
throws AccessControlException {
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/SchemaTypeWizardBuilder.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/SchemaTypeWizardBuilder.java
index b646d0a..77366e6 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/SchemaTypeWizardBuilder.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/SchemaTypeWizardBuilder.java
@@ -32,6 +32,7 @@
import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel;
import org.apache.syncope.client.console.wizards.BaseAjaxWizardBuilder;
+import org.apache.syncope.client.ui.commons.BaseLogin;
import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
import org.apache.syncope.common.lib.to.DerSchemaTO;
@@ -163,7 +164,7 @@
}
});
locale.setRequired(true).hideLabel();
- locale.setChoices(SyncopeWebApplication.SUPPORTED_LOCALES.stream().
+ locale.setChoices(BaseLogin.SUPPORTED_LOCALES.stream().
map(Objects::toString).collect(Collectors.toList()));
locale.addValidator(validatable -> {
try {
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/status/ChangePasswordModal.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/status/ChangePasswordModal.java
index 5d56dba..0e865ec 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/status/ChangePasswordModal.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/status/ChangePasswordModal.java
@@ -58,7 +58,7 @@
this.wrapper = wrapper;
- final PasswordPanel passwordPanel = new PasswordPanel("passwordPanel", wrapper, false);
+ final PasswordPanel passwordPanel = new PasswordPanel("passwordPanel", wrapper, false, false);
passwordPanel.setOutputMarkupId(true);
add(passwordPanel);
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/bootstrap/dialog/BaseModal.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/bootstrap/dialog/BaseModal.java
index 861394e..2bdd5b4 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/bootstrap/dialog/BaseModal.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/bootstrap/dialog/BaseModal.java
@@ -102,8 +102,6 @@
this.windowClosedCallback = null;
components = new ArrayList<>();
- // Note: not adding this would imply adding WebjarsJavaScriptResourceReference about JQuery resizable and mouse
- // add(new Resizable().withChildSelector(".modal-content"));
// Note: not adding this would imply adding of WebjarsJavaScriptResourceReference about JQuery draggable
add(new Draggable(new DraggableConfig().withHandle(".modal-header").withCursor("move")));
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/BinaryFieldPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/BinaryFieldPanel.java
index bc48ae0..bc46754 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/BinaryFieldPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/BinaryFieldPanel.java
@@ -18,6 +18,8 @@
*/
package org.apache.syncope.client.console.wicket.markup.html.form;
+import org.apache.syncope.client.ui.commons.markup.html.form.BinaryFieldDownload;
+
import static de.agilecoders.wicket.jquery.JQuery.$;
import de.agilecoders.wicket.extensions.markup.html.bootstrap.form.fileinput.BootstrapFileInputField;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AbstractAttrsWizardStep.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AbstractAttrsWizardStep.java
index f4ae2c3..600fc1d 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AbstractAttrsWizardStep.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AbstractAttrsWizardStep.java
@@ -285,7 +285,7 @@
break;
case Binary:
- final PageReference pageRef = getPageReference();
+ PageReference pageRef = getPageReference();
panel = new BinaryFieldPanel(
"panel",
plainSchema.getLabel(SyncopeConsoleSession.get().getLocale()),
@@ -299,7 +299,6 @@
protected PageReference getPageReference() {
return pageRef;
}
-
};
if (required) {
panel.addRequiredLabel();
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/UserDetails.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/UserDetails.java
index d8c49e3..e067ef1 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/UserDetails.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/UserDetails.java
@@ -137,7 +137,7 @@
super(id);
setOutputMarkupId(true);
add(new Label("warning", new ResourceModel("password.change.warning")));
- add(new PasswordPanel("passwordPanel", wrapper, templateMode));
+ add(new PasswordPanel("passwordPanel", wrapper, false, templateMode));
}
}
}
diff --git a/client/idrepo/enduser/pom.xml b/client/idrepo/enduser/pom.xml
index f7ed9fa..9bf1786 100644
--- a/client/idrepo/enduser/pom.xml
+++ b/client/idrepo/enduser/pom.xml
@@ -110,14 +110,16 @@
<groupId>com.lmax</groupId>
<artifactId>disruptor</artifactId>
</dependency>
+
<dependency>
- <groupId>commons-logging</groupId>
- <artifactId>commons-logging</artifactId>
- <scope>provided</scope>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <scope>test</scope>
</dependency>
<dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>jcl-over-slf4j</artifactId>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter</artifactId>
+ <scope>test</scope>
</dependency>
</dependencies>
@@ -240,6 +242,7 @@
<configuration>
<jvmArguments>
-Dwicket.core.settings.general.configuration-type=development
+ -XX:HotswapAgent=fatjar
-Xdebug -Xrunjdwp:transport=dt_socket,address=8004,server=y,suspend=n
</jvmArguments>
<profiles>
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/BookmarkablePageLinkBuilder.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/BookmarkablePageLinkBuilder.java
new file mode 100644
index 0000000..7f5c806
--- /dev/null
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/BookmarkablePageLinkBuilder.java
@@ -0,0 +1,45 @@
+/*
+ * 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.enduser;
+
+import org.apache.wicket.markup.html.WebPage;
+import org.apache.wicket.markup.html.link.BookmarkablePageLink;
+
+public final class BookmarkablePageLinkBuilder {
+
+ public static <T extends WebPage> BookmarkablePageLink<T> build(
+ final String key, final Class<T> defaultPageClass) {
+
+ return build(key, key, defaultPageClass);
+ }
+
+ public static <T extends WebPage> BookmarkablePageLink<T> build(
+ final String key, final String id, final Class<T> defaultPageClass) {
+
+ @SuppressWarnings("unchecked")
+ Class<T> pageClass = (Class<T>) SyncopeWebApplication.get().getPageClass(key);
+ return new BookmarkablePageLink<>(
+ id,
+ pageClass == null ? defaultPageClass : pageClass);
+ }
+
+ private BookmarkablePageLinkBuilder() {
+ // private constructor for static utility class
+ }
+}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/PreferenceManager.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/PreferenceManager.java
new file mode 100644
index 0000000..845e7a6
--- /dev/null
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/PreferenceManager.java
@@ -0,0 +1,172 @@
+/*
+ * 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.enduser;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.core.type.TypeReference;
+import java.io.IOException;
+import java.io.Serializable;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Base64;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.math.NumberUtils;
+import org.apache.wicket.util.cookies.CookieDefaults;
+import org.apache.wicket.util.cookies.CookieUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class PreferenceManager implements Serializable {
+
+ private static final long serialVersionUID = 3581434664555284193L;
+
+ private static final Logger LOG = LoggerFactory.getLogger(PreferenceManager.class);
+
+ private static final String COOKIE_NAME = "syncope2EnduserPrefs";
+
+ private static final int ONE_YEAR_TIME = 60 * 60 * 24 * 365;
+
+ private static final ObjectMapper MAPPER = new ObjectMapper();
+
+ private static final TypeReference<Map<String, String>> MAP_TYPE_REF = new TypeReference<Map<String, String>>() {
+ };
+
+ private static final List<Integer> PAGINATOR_CHOICES = Arrays.asList(new Integer[] { 10, 25, 50 });
+
+ private static final CookieUtils COOKIE_UTILS;
+
+ static {
+ CookieDefaults cookieDefaults = new CookieDefaults();
+ cookieDefaults.setMaxAge(ONE_YEAR_TIME);
+ COOKIE_UTILS = new CookieUtils(cookieDefaults);
+ }
+
+ public List<Integer> getPaginatorChoices() {
+ return PAGINATOR_CHOICES;
+ }
+
+ private Map<String, String> getPrefs(final String value) {
+ Map<String, String> prefs;
+ try {
+ if (StringUtils.isNotBlank(value)) {
+ prefs = MAPPER.readValue(value, MAP_TYPE_REF);
+ } else {
+ throw new Exception("Invalid cookie value '" + value + "'");
+ }
+ } catch (Exception e) {
+ LOG.debug("No preferences found", e);
+ prefs = new HashMap<>();
+ }
+
+ return prefs;
+ }
+
+ private String setPrefs(final Map<String, String> prefs) throws IOException {
+ StringWriter writer = new StringWriter();
+ MAPPER.writeValue(writer, prefs);
+
+ return writer.toString();
+ }
+
+ public String get(final String key) {
+ String result = null;
+
+ String prefString = COOKIE_UTILS.load(COOKIE_NAME);
+ if (prefString != null) {
+ Map<String, String> prefs = getPrefs(new String(Base64.getDecoder().decode(prefString.getBytes())));
+ result = prefs.get(key);
+ }
+
+ return result;
+ }
+
+ public Integer getPaginatorRows(final String key) {
+ Integer result = getPaginatorChoices().get(0);
+
+ String value = get(key);
+ if (value != null) {
+ result = NumberUtils.toInt(value, 10);
+ }
+
+ return result;
+ }
+
+ public List<String> getList(final String key) {
+ List<String> result = new ArrayList<>();
+
+ String compound = get(key);
+
+ if (StringUtils.isNotBlank(compound)) {
+ String[] items = compound.split(";");
+ result.addAll(Arrays.asList(items));
+ }
+
+ return result;
+ }
+
+ public void set(final Map<String, List<String>> prefs) {
+ Map<String, String> current = new HashMap<>();
+
+ String prefString = COOKIE_UTILS.load(COOKIE_NAME);
+ if (prefString != null) {
+ current.putAll(getPrefs(new String(Base64.getDecoder().decode(prefString.getBytes()))));
+ }
+
+ // after retrieved previous setting in order to overwrite the key ...
+ prefs.forEach((key, values) -> {
+ current.put(key, StringUtils.join(values, ";"));
+ });
+
+ try {
+ COOKIE_UTILS.save(COOKIE_NAME, Base64.getEncoder().encodeToString(setPrefs(current).getBytes()));
+ } catch (IOException e) {
+ LOG.error("Could not save {} info: {}", getClass().getSimpleName(), current, e);
+ }
+ }
+
+ public void set(final String key, final String value) {
+ String prefString = COOKIE_UTILS.load(COOKIE_NAME);
+
+ final Map<String, String> current = new HashMap<>();
+ if (prefString != null) {
+ current.putAll(getPrefs(new String(Base64.getDecoder().decode(prefString.getBytes()))));
+ }
+
+ // after retrieved previous setting in order to overwrite the key ...
+ current.put(key, value);
+
+ try {
+ COOKIE_UTILS.save(COOKIE_NAME, Base64.getEncoder().encodeToString(setPrefs(current).getBytes()));
+ } catch (IOException e) {
+ LOG.error("Could not save {} info: {}", getClass().getSimpleName(), current, e);
+ }
+ }
+
+ public void setList(final String key, final List<String> values) {
+ set(key, StringUtils.join(values, ";"));
+ }
+
+ public void setList(final Map<String, List<String>> prefs) {
+ set(prefs);
+ }
+}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserConstants.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserConstants.java
deleted file mode 100644
index 0a683a9..0000000
--- a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserConstants.java
+++ /dev/null
@@ -1,35 +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.enduser;
-
-public final class SyncopeEnduserConstants {
-
- public static final String CAPTCHA_SESSION_KEY = "captcha";
-
- public static final String XSRF_COOKIE = "XSRF-TOKEN";
-
- public static final String XSRF_HEADER_NAME = "X-XSRF-TOKEN";
-
- public static final String MEMBERSHIP_ATTR_SEPARATOR = "#";
-
- private SyncopeEnduserConstants() {
- // private constructor for utility class
- }
-
-}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserRequestCycleListener.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserRequestCycleListener.java
new file mode 100644
index 0000000..a0e2192
--- /dev/null
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserRequestCycleListener.java
@@ -0,0 +1,104 @@
+/*
+ * 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.enduser;
+
+import java.security.AccessControlException;
+import javax.ws.rs.BadRequestException;
+import javax.ws.rs.ForbiddenException;
+import javax.xml.ws.WebServiceException;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.enduser.pages.Login;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.wicket.authorization.UnauthorizedInstantiationException;
+import org.apache.wicket.core.request.handler.PageProvider;
+import org.apache.wicket.core.request.handler.RenderPageRequestHandler;
+import org.apache.wicket.markup.html.pages.ExceptionErrorPage;
+import org.apache.wicket.protocol.http.PageExpiredException;
+import org.apache.wicket.request.IRequestHandler;
+import org.apache.wicket.request.component.IRequestablePage;
+import org.apache.wicket.request.cycle.IRequestCycleListener;
+import org.apache.wicket.request.cycle.RequestCycle;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SyncopeEnduserRequestCycleListener implements IRequestCycleListener {
+
+ private static final Logger LOG = LoggerFactory.getLogger(SyncopeEnduserRequestCycleListener.class);
+
+ private Throwable instanceOf(final Exception e, final Class<? extends Exception> clazz) {
+ return clazz.isAssignableFrom(e.getClass())
+ ? e
+ : e.getCause() != null && clazz.isAssignableFrom(e.getCause().getClass())
+ ? e.getCause()
+ : e.getCause() != null && e.getCause().getCause() != null
+ && clazz.isAssignableFrom(e.getCause().getCause().getClass())
+ ? e.getCause().getCause()
+ : null;
+ }
+
+ @Override
+ public IRequestHandler onException(final RequestCycle cycle, final Exception e) {
+ LOG.error("Exception found", e);
+
+ PageParameters errorParameters = new PageParameters();
+
+ IRequestablePage errorPage;
+ if (instanceOf(e, UnauthorizedInstantiationException.class) != null) {
+ errorParameters.add("errorMessage", SyncopeEnduserSession.Error.AUTHORIZATION.fallback());
+ errorPage = new Login(errorParameters);
+ } else if (instanceOf(e, AccessControlException.class) != null) {
+ if (StringUtils.containsIgnoreCase(instanceOf(e, AccessControlException.class).getMessage(), "expired")) {
+ errorParameters.add("errorMessage", SyncopeEnduserSession.Error.SESSION_EXPIRED.fallback());
+ } else {
+ errorParameters.add("errorMessage", SyncopeEnduserSession.Error.AUTHORIZATION.fallback());
+ }
+ errorPage = new Login(errorParameters);
+ } else if (instanceOf(e, PageExpiredException.class) != null || !SyncopeEnduserSession.get().isSignedIn()) {
+ errorParameters.add("errorMessage", SyncopeEnduserSession.Error.SESSION_EXPIRED.fallback());
+ errorPage = new Login(errorParameters);
+ } else if (instanceOf(e, BadRequestException.class) != null
+ || instanceOf(e, WebServiceException.class) != null
+ || instanceOf(e, SyncopeClientException.class) != null) {
+
+ errorParameters.add("errorMessage", SyncopeEnduserSession.Error.REST.fallback());
+ errorPage = new Login(errorParameters);
+ } else {
+ Throwable cause = instanceOf(e, ForbiddenException.class);
+ if (cause == null) {
+ // redirect to default Wicket error page
+ errorPage = new ExceptionErrorPage(e, null);
+ } else {
+ errorParameters.add("errorMessage", cause.getMessage());
+ errorPage = new Login(errorParameters);
+ }
+ }
+
+ if (errorPage instanceof Login) {
+ try {
+ SyncopeEnduserSession.get().invalidate();
+ } catch (Throwable t) {
+ // ignore
+ LOG.debug("Unexpected error while forcing logout after error", t);
+ }
+ }
+
+ return new RenderPageRequestHandler(new PageProvider(errorPage));
+ }
+}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserSession.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserSession.java
index 7ea4470..81f8a25 100644
--- a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserSession.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserSession.java
@@ -18,21 +18,6 @@
*/
package org.apache.syncope.client.enduser;
-import java.security.AccessControlException;
-import java.text.DateFormat;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Optional;
-import java.util.concurrent.Callable;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.Future;
-import java.util.stream.Collectors;
-import javax.ws.rs.BadRequestException;
-import javax.ws.rs.ForbiddenException;
-import javax.ws.rs.core.EntityTag;
-import javax.ws.rs.core.MediaType;
-import javax.xml.ws.WebServiceException;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.commons.lang3.time.FastDateFormat;
@@ -43,24 +28,63 @@
import org.apache.syncope.client.ui.commons.BaseSession;
import org.apache.syncope.common.lib.SyncopeClientException;
import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.lib.info.PlatformInfo;
+import org.apache.syncope.common.lib.info.SystemInfo;
import org.apache.syncope.common.lib.to.UserTO;
-import org.apache.syncope.common.lib.types.ClientExceptionType;
import org.apache.syncope.common.lib.types.IdRepoEntitlement;
import org.apache.syncope.common.rest.api.RESTHeaders;
+import org.apache.syncope.common.rest.api.service.SyncopeService;
import org.apache.wicket.Session;
-import org.apache.wicket.protocol.http.WebSession;
+import org.apache.wicket.authroles.authentication.AuthenticatedWebSession;
+import org.apache.wicket.authroles.authorization.strategies.role.Roles;
import org.apache.wicket.request.Request;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.task.TaskRejectedException;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+import javax.ws.rs.BadRequestException;
+import javax.ws.rs.ForbiddenException;
+import javax.ws.rs.core.EntityTag;
+import javax.ws.rs.core.MediaType;
+import javax.xml.ws.WebServiceException;
+import java.security.AccessControlException;
+import java.text.DateFormat;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Future;
+import java.util.stream.Collectors;
+import org.apache.syncope.common.lib.types.ClientExceptionType;
-/**
- * Custom Syncope Enduser Session class.
- */
-public class SyncopeEnduserSession extends WebSession implements BaseSession {
+public class SyncopeEnduserSession extends AuthenticatedWebSession implements BaseSession {
- private static final long serialVersionUID = 1284946129513378647L;
+ private static final long serialVersionUID = 747562246415852166L;
+
+ public enum Error {
+ INVALID_SECURITY_ANSWER("invalid.security.answer", "Invalid Security Answer"),
+ SESSION_EXPIRED("error.session.expired", "Session expired: please login again"),
+ AUTHORIZATION("error.authorization", "Insufficient access rights when performing the requested operation"),
+ REST("error.rest", "There was an error while contacting the Core server");
+
+ private final String key;
+
+ private final String fallback;
+
+ Error(final String key, final String fallback) {
+ this.key = key;
+ this.fallback = fallback;
+ }
+
+ public String key() {
+ return key;
+ }
+
+ public String fallback() {
+ return fallback;
+ }
+ }
private static final Logger LOG = LoggerFactory.getLogger(SyncopeEnduserSession.class);
@@ -68,9 +92,9 @@
private final SyncopeClient anonymousClient;
- private SyncopeClient client;
+ private final PlatformInfo platformInfo;
- private UserTO selfTO;
+ private final SystemInfo systemInfo;
private final Map<Class<?>, Object> services = Collections.synchronizedMap(new HashMap<>());
@@ -78,6 +102,10 @@
private String domain;
+ private SyncopeClient client;
+
+ private UserTO selfTO;
+
public static SyncopeEnduserSession get() {
return (SyncopeEnduserSession) Session.get();
}
@@ -86,22 +114,39 @@
super(request);
clientFactory = SyncopeWebApplication.get().newClientFactory();
- anonymousClient = clientFactory.create(new AnonymousAuthenticationHandler(
- SyncopeWebApplication.get().getAnonymousUser(),
- SyncopeWebApplication.get().getAnonymousKey()));
+ anonymousClient = clientFactory.
+ create(new AnonymousAuthenticationHandler(
+ SyncopeWebApplication.get().getAnonymousUser(),
+ SyncopeWebApplication.get().getAnonymousKey()));
+
+ platformInfo = getAnonymousService(SyncopeService.class).platform();
+ systemInfo = getAnonymousService(SyncopeService.class).system();
executor = new ThreadPoolTaskExecutor();
executor.setWaitForTasksToCompleteOnShutdown(false);
- executor.setCorePoolSize(SyncopeWebApplication.get().getCorePoolSize());
- executor.setMaxPoolSize(SyncopeWebApplication.get().getMaxPoolSize());
- executor.setQueueCapacity(SyncopeWebApplication.get().getQueueCapacity());
executor.initialize();
}
protected String message(final SyncopeClientException sce) {
- return sce.getType().name() + ": " + sce.getElements().stream().collect(Collectors.joining(", "));
+ Error error = null;
+ if (sce.getType() == ClientExceptionType.InvalidSecurityAnswer) {
+ error = Error.INVALID_SECURITY_ANSWER;
+ }
+ if (error == null) {
+ return sce.getType().name() + ": " + sce.getElements().stream().collect(Collectors.joining(", "));
+ }
+ return getApplication().getResourceSettings().getLocalizer().
+ getString(error.key(), null, null, null, null, error.fallback());
}
+ /**
+ * Extract and localize (if translation available) the actual message from the given exception; then, report it
+ * via {@link Session#error(java.io.Serializable)}.
+ *
+ * @see org.apache.syncope.client.lib.RestClientExceptionMapper
+ *
+ * @param e raised exception
+ */
@Override
public void onException(final Exception e) {
Throwable root = ExceptionUtils.getRootCause(e);
@@ -111,8 +156,6 @@
SyncopeClientException sce = (SyncopeClientException) root;
message = sce.isComposite()
? sce.asComposite().getExceptions().stream().map(this::message).collect(Collectors.joining("; "))
- : sce.getType() == ClientExceptionType.InvalidSecurityAnswer
- ? getApplication().getResourceSettings().getLocalizer().getString("invalid.security.answer", null)
: message(sce);
} else if (root instanceof AccessControlException || root instanceof ForbiddenException) {
Error error = StringUtils.containsIgnoreCase(message, "expired")
@@ -130,15 +173,31 @@
error(message);
}
- public void cleanup() {
- client = null;
- selfTO = null;
- services.clear();
+ public MediaType getMediaType() {
+ return clientFactory.getContentType().getMediaType();
+ }
+
+ public SyncopeClient getAnonymousClient() {
+ return anonymousClient;
+ }
+
+ public void execute(final Runnable command) {
+ try {
+ executor.execute(command);
+ } catch (TaskRejectedException e) {
+ LOG.error("Could not execute {}", command, e);
+ }
}
@Override
- public String getJWT() {
- return Optional.ofNullable(client).map(SyncopeClient::getJWT).orElse(null);
+ public <T> Future<T> execute(final Callable<T> command) {
+ try {
+ return executor.submit(command);
+ } catch (TaskRejectedException e) {
+ LOG.error("Could not execute {}", command, e);
+
+ return new CompletableFuture<>();
+ }
}
@Override
@@ -151,24 +210,30 @@
return StringUtils.isBlank(domain) ? SyncopeConstants.MASTER_DOMAIN : domain;
}
- private void afterAuthentication(final String username) {
- try {
- selfTO = client.self().getRight();
- } catch (ForbiddenException e) {
- LOG.warn("Could not read self(), probably in a {} scenario", IdRepoEntitlement.MUST_CHANGE_PASSWORD, e);
-
- selfTO = new UserTO();
- selfTO.setUsername(username);
- selfTO.setMustChangePassword(true);
- }
-
- // bind explicitly this session to have a stateful behavior during http requests, unless session will
- // expire at each request
- this.bind();
+ @Override
+ public String getJWT() {
+ return client == null ? null : client.getJWT();
}
+ @Override
+ public Roles getRoles() {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public PlatformInfo getPlatformInfo() {
+ return platformInfo;
+ }
+
+ public SystemInfo getSystemInfo() {
+ return systemInfo;
+ }
+
+ @Override
public boolean authenticate(final String username, final String password) {
boolean authenticated = false;
+ if (SyncopeWebApplication.get().getAdminUser().equalsIgnoreCase(username)) {
+ return authenticated;
+ }
try {
client = clientFactory.setDomain(getDomain()).create(username, password);
@@ -199,6 +264,36 @@
return authenticated;
}
+ private void afterAuthentication(final String username) {
+ try {
+ selfTO = client.self().getRight();
+ } catch (ForbiddenException e) {
+ LOG.warn("Could not read self(), probably in a {} scenario", IdRepoEntitlement.MUST_CHANGE_PASSWORD, e);
+
+ selfTO = new UserTO();
+ selfTO.setUsername(username);
+ selfTO.setMustChangePassword(true);
+ }
+
+ // bind explicitly this session to have a stateful behavior during http requests, unless session will
+ // expire at each request
+ this.bind();
+ }
+
+ protected boolean isAuthenticated() {
+ return client != null && client.getJWT() != null;
+ }
+
+ protected boolean isMustChangePassword() {
+ return selfTO != null && selfTO.isMustChangePassword();
+ }
+
+ public void cleanup() {
+ client = null;
+ selfTO = null;
+ services.clear();
+ }
+
@Override
public void invalidate() {
if (isAuthenticated()) {
@@ -214,9 +309,30 @@
super.invalidate();
}
- @Override
- public <T> T getAnonymousService(final Class<T> serviceClass) {
- return getService(serviceClass);
+ public UserTO getSelfTO() {
+ return getSelfTO(false);
+ }
+
+ public UserTO getSelfTO(final boolean reload) {
+ if (reload) {
+ afterAuthentication(selfTO.getUsername());
+ }
+ return selfTO;
+ }
+
+ @SuppressWarnings("unchecked")
+ private <T> T getCachedService(final Class<T> serviceClass) {
+ T service;
+ if (services.containsKey(serviceClass)) {
+ service = (T) services.get(serviceClass);
+ } else {
+ service = client.getService(serviceClass);
+ services.put(serviceClass, service);
+ }
+
+ WebClient.client(service).type(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON);
+
+ return service;
}
@Override
@@ -237,43 +353,6 @@
return serviceInstance;
}
- public UserTO getSelfTO() {
- if (selfTO == null) {
- throw new IllegalArgumentException("User not authenticated");
- }
- return selfTO;
- }
-
- @Override
- public <T> Future<T> execute(final Callable<T> command) {
- try {
- return executor.submit(command);
- } catch (TaskRejectedException e) {
- LOG.error("Could not execute {}", command, e);
-
- return new CompletableFuture<>();
- }
- }
-
- public boolean isAuthenticated() {
- return client != null && client.getJWT() != null;
- }
-
- @SuppressWarnings("unchecked")
- private <T> T getCachedService(final Class<T> serviceClass) {
- T service;
- if (services.containsKey(serviceClass)) {
- service = (T) services.get(serviceClass);
- } else {
- service = client.getService(serviceClass);
- services.put(serviceClass, service);
- }
-
- WebClient.client(service).type(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON);
-
- return service;
- }
-
@Override
public <T> void resetClient(final Class<T> service) {
T serviceInstance = getCachedService(service);
@@ -284,4 +363,9 @@
public FastDateFormat getDateFormat() {
return FastDateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, getLocale());
}
+
+ @Override
+ public <T> T getAnonymousService(final Class<T> serviceClass) {
+ return getAnonymousClient().getService(serviceClass);
+ }
}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeWebApplication.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeWebApplication.java
index af4fa3a..37ca700 100644
--- a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeWebApplication.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeWebApplication.java
@@ -25,9 +25,11 @@
import de.agilecoders.wicket.core.Bootstrap;
import de.agilecoders.wicket.core.settings.BootstrapSettings;
import de.agilecoders.wicket.core.settings.IBootstrapSettings;
+import de.agilecoders.wicket.core.settings.SingleThemeProvider;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
+import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
@@ -40,26 +42,26 @@
import org.apache.commons.io.monitor.FileAlterationMonitor;
import org.apache.commons.io.monitor.FileAlterationObserver;
import org.apache.commons.lang3.BooleanUtils;
+import org.apache.commons.lang3.ClassUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.syncope.client.enduser.init.ClassPathScanImplementationLookup;
-import org.apache.syncope.client.enduser.assets.SyncopeEnduserCss;
-import org.apache.syncope.client.enduser.model.CustomAttributesInfo;
+import org.apache.syncope.client.enduser.layout.UserFormLayoutInfo;
+import org.apache.syncope.client.enduser.pages.BasePage;
+import org.apache.syncope.client.enduser.pages.Dashboard;
import org.apache.syncope.client.enduser.pages.Login;
import org.apache.syncope.client.enduser.pages.MustChangePassword;
-import org.apache.syncope.client.enduser.pages.Self;
import org.apache.syncope.client.enduser.pages.SelfConfirmPasswordReset;
+import org.apache.syncope.client.enduser.panels.Sidebar;
import org.apache.syncope.client.lib.SyncopeClientFactoryBean;
import org.apache.syncope.client.ui.commons.SyncopeUIRequestCycleListener;
import org.apache.syncope.client.ui.commons.annotations.Resource;
+import org.apache.syncope.client.ui.commons.themes.AdminLTE;
import org.apache.syncope.common.keymaster.client.api.model.NetworkService;
import org.apache.syncope.common.keymaster.client.api.ServiceOps;
import org.apache.syncope.common.lib.PropertyUtils;
import org.apache.wicket.Page;
import org.apache.wicket.Session;
import org.apache.wicket.WicketRuntimeException;
-import org.apache.wicket.markup.head.CssHeaderItem;
-import org.apache.wicket.markup.head.IHeaderResponse;
-import org.apache.wicket.markup.html.IHeaderContributor;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.protocol.http.ResourceIsolationRequestCycleListener;
import org.apache.wicket.protocol.http.WebApplication;
@@ -74,7 +76,6 @@
import org.apache.wicket.request.resource.AbstractResource;
import org.apache.wicket.request.resource.IResource;
import org.apache.wicket.request.resource.ResourceReference;
-import org.apache.wicket.resource.JQueryResourceReference;
import org.apache.wicket.util.lang.Args;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -88,7 +89,7 @@
private static final String ENDUSER_PROPERTIES = "enduser.properties";
- private static final String CUSTOM_FORM_ATTRIBUTES_FILE = "customFormAttributes.json";
+ private static final String CUSTOM_FORM_LAYOUT_FILE = "customFormLayout.json";
public static final List<Locale> SUPPORTED_LOCALES = List.of(
Locale.ENGLISH, Locale.ITALIAN, new Locale("pt", "BR"), new Locale("ru"), Locale.JAPANESE);
@@ -125,11 +126,36 @@
private Integer maxUploadFileSizeMB;
- private FileAlterationMonitor customFormAttributesMonitor;
+ private FileAlterationMonitor customFormLayoutMonitor;
- private Map<String, CustomAttributesInfo> customFormAttributes;
+ private Map<String, Class<? extends BasePage>> pageClasses;
- protected void setSecurityHeaders(final Properties props, final WebResponse response) {
+ private Class<? extends Sidebar> sidebar;
+
+ private UserFormLayoutInfo customFormLayout;
+
+ @SuppressWarnings("unchecked")
+ protected void populatePageClasses(final Properties props) {
+ Enumeration<String> propNames = (Enumeration<String>) props.propertyNames();
+ while (propNames.hasMoreElements()) {
+ String className = propNames.nextElement();
+ if (className.startsWith("page.")) {
+ try {
+ Class<?> clazz = ClassUtils.getClass(props.getProperty(className));
+ if (BasePage.class.isAssignableFrom(clazz)) {
+ pageClasses.put(
+ StringUtils.substringAfter(className, "page."), (Class<? extends BasePage>) clazz);
+ } else {
+ LOG.warn("{} does not extend {}, ignoring...", clazz.getName(), BasePage.class.getName());
+ }
+ } catch (ClassNotFoundException e) {
+ LOG.error("While looking for class identified by property '{}'", className, e);
+ }
+ }
+ }
+ }
+
+ protected static void setSecurityHeaders(final Properties props, final WebResponse response) {
@SuppressWarnings("unchecked")
Enumeration<String> propNames = (Enumeration<String>) props.propertyNames();
while (propNames.hasMoreElements()) {
@@ -199,33 +225,31 @@
maxPoolSize = 50;
}
- // read customFormAttributes.json
- File enduserDir;
- try (InputStream is = SyncopeWebApplication.class.getResourceAsStream('/' + CUSTOM_FORM_ATTRIBUTES_FILE)) {
- customFormAttributes = MAPPER.readValue(is,
- new TypeReference<HashMap<String, CustomAttributesInfo>>() {
+ // read customFormLayout.json
+ try (InputStream is = SyncopeWebApplication.class.getResourceAsStream('/' + CUSTOM_FORM_LAYOUT_FILE)) {
+ customFormLayout = MAPPER.readValue(is, new TypeReference<UserFormLayoutInfo>() {
});
- enduserDir = new File(props.getProperty("enduser.directory"));
+ File enduserDir = new File(props.getProperty("enduser.directory"));
boolean existsEnduserDir = enduserDir.exists() && enduserDir.canRead() && enduserDir.isDirectory();
if (existsEnduserDir) {
- File customFormAttributesFile = FileUtils.getFile(enduserDir, CUSTOM_FORM_ATTRIBUTES_FILE);
- if (customFormAttributesFile.exists()
- && customFormAttributesFile.canRead()
- && customFormAttributesFile.isFile()) {
- customFormAttributes = MAPPER.readValue(FileUtils.openInputStream(customFormAttributesFile),
- new TypeReference<HashMap<String, CustomAttributesInfo>>() {
+ File customFormLayoutFile = FileUtils.getFile(enduserDir, CUSTOM_FORM_LAYOUT_FILE);
+ if (customFormLayoutFile.exists()
+ && customFormLayoutFile.canRead()
+ && customFormLayoutFile.isFile()) {
+ customFormLayout = MAPPER.readValue(FileUtils.openInputStream(customFormLayoutFile),
+ new TypeReference<UserFormLayoutInfo>() {
});
}
}
FileAlterationObserver observer = existsEnduserDir
? new FileAlterationObserver(
enduserDir,
- pathname -> StringUtils.contains(pathname.getPath(), CUSTOM_FORM_ATTRIBUTES_FILE))
+ pathname -> StringUtils.contains(pathname.getPath(), CUSTOM_FORM_LAYOUT_FILE))
: new FileAlterationObserver(
- SyncopeWebApplication.class.getResource('/' + CUSTOM_FORM_ATTRIBUTES_FILE).getFile(),
- pathname -> StringUtils.contains(pathname.getPath(), CUSTOM_FORM_ATTRIBUTES_FILE));
+ SyncopeWebApplication.class.getResource('/' + CUSTOM_FORM_LAYOUT_FILE).getFile(),
+ pathname -> StringUtils.contains(pathname.getPath(), CUSTOM_FORM_LAYOUT_FILE));
- customFormAttributesMonitor = new FileAlterationMonitor(5000);
+ customFormLayoutMonitor = new FileAlterationMonitor(5000);
FileAlterationListener listener = new FileAlterationListenerAdaptor() {
@@ -233,13 +257,13 @@
public void onFileChange(final File file) {
try {
LOG.trace("{} has changed. Reloading form attributes customization configuration.",
- CUSTOM_FORM_ATTRIBUTES_FILE);
- customFormAttributes = MAPPER.readValue(FileUtils.openInputStream(file),
- new TypeReference<HashMap<String, CustomAttributesInfo>>() {
+ CUSTOM_FORM_LAYOUT_FILE);
+ customFormLayout = MAPPER.readValue(FileUtils.openInputStream(file),
+ new TypeReference<UserFormLayoutInfo>() {
});
} catch (IOException e) {
LOG.error("{} While reading app customization configuration.",
- CUSTOM_FORM_ATTRIBUTES_FILE, e);
+ CUSTOM_FORM_LAYOUT_FILE, e);
}
}
@@ -247,34 +271,44 @@
public void onFileCreate(final File file) {
try {
LOG.trace("{} has been created. Loading form attributes customization configuration.",
- CUSTOM_FORM_ATTRIBUTES_FILE);
- customFormAttributes = MAPPER.readValue(FileUtils.openInputStream(file),
- new TypeReference<HashMap<String, CustomAttributesInfo>>() {
+ CUSTOM_FORM_LAYOUT_FILE);
+ customFormLayout = MAPPER.readValue(FileUtils.openInputStream(file),
+ new TypeReference<UserFormLayoutInfo>() {
});
} catch (IOException e) {
LOG.error("{} While reading app customization configuration.",
- CUSTOM_FORM_ATTRIBUTES_FILE, e);
+ CUSTOM_FORM_LAYOUT_FILE, e);
}
}
@Override
public void onFileDelete(final File file) {
LOG.trace("{} has been deleted. Resetting form attributes customization configuration.",
- CUSTOM_FORM_ATTRIBUTES_FILE);
- customFormAttributes = null;
+ CUSTOM_FORM_LAYOUT_FILE);
+ customFormLayout = null;
}
};
observer.addListener(listener);
- customFormAttributesMonitor.addObserver(observer);
- customFormAttributesMonitor.start();
+ customFormLayoutMonitor.addObserver(observer);
+ customFormLayoutMonitor.start();
} catch (Exception e) {
- throw new WicketRuntimeException("Could not read " + CUSTOM_FORM_ATTRIBUTES_FILE, e);
+ throw new WicketRuntimeException("Could not read " + CUSTOM_FORM_LAYOUT_FILE, e);
}
+ // process page properties
+ pageClasses = new HashMap<>();
+ populatePageClasses(props);
+ pageClasses = Collections.unmodifiableMap(pageClasses);
+
+ buildSidebarClass(props);
+
// Application settings
IBootstrapSettings settings = new BootstrapSettings();
+ // set theme provider
+ settings.setThemeProvider(new SingleThemeProvider(new AdminLTE()));
+
// install application settings
Bootstrap.install(this, settings);
@@ -282,25 +316,8 @@
getResourceSettings().setUseDefaultOnMissingResource(true);
getResourceSettings().setThrowExceptionOnMissingResource(false);
- getJavaScriptLibrarySettings().setJQueryReference(JQueryResourceReference.getV2());
-
- getResourceSettings().setThrowExceptionOnMissingResource(true);
-
getMarkupSettings().setStripWicketTags(true);
getMarkupSettings().setCompressWhitespace(true);
- getMarkupSettings().setStripComments(true);
-
- // add some css assets as Java Wicket resource in order to set Bootstrap css as a dependency of those
- // and stop it to override the custom css rules
- getHeaderContributorListeners().add(new IHeaderContributor() {
-
- private static final long serialVersionUID = -8955205747168484695L;
-
- @Override
- public void renderHead(final IHeaderResponse response) {
- response.render(CssHeaderItem.forReference(SyncopeEnduserCss.INSTANCE));
- }
- });
getRequestCycleListeners().add(new SyncopeUIRequestCycleListener() {
@@ -318,7 +335,6 @@
protected IRequestablePage getErrorPage(final PageParameters errorParameters) {
return new Login(errorParameters);
}
-
});
if (BooleanUtils.toBoolean(props.getProperty("x-forward"))) {
@@ -388,11 +404,11 @@
@Override
protected void onDestroy() {
- if (customFormAttributesMonitor != null) {
+ if (customFormLayoutMonitor != null) {
try {
- customFormAttributesMonitor.stop(0);
+ customFormLayoutMonitor.stop(0);
} catch (Exception e) {
- LOG.error("{} While stopping file monitor", CUSTOM_FORM_ATTRIBUTES_FILE, e);
+ LOG.error("{} While stopping file monitor", CUSTOM_FORM_LAYOUT_FILE, e);
}
}
}
@@ -400,11 +416,37 @@
@Override
public Class<? extends Page> getHomePage() {
return SyncopeEnduserSession.get().isAuthenticated()
- && SyncopeEnduserSession.get().getSelfTO().isMustChangePassword()
+ && SyncopeEnduserSession.get().isMustChangePassword()
? MustChangePassword.class
: SyncopeEnduserSession.get().isAuthenticated()
- ? Self.class
- : Login.class;
+ ? getPageClass("profile", Dashboard.class)
+ : getSignInPageClass();
+ }
+
+ public ClassPathScanImplementationLookup getLookup() {
+ return lookup;
+ }
+
+ @SuppressWarnings("unchecked")
+ private void buildSidebarClass(final Properties props) {
+ try {
+ Class<?> clazz = ClassUtils.getClass(props.getProperty("sidebar", Sidebar.class.getCanonicalName()));
+ if (Sidebar.class.isAssignableFrom(clazz)) {
+ sidebar = (Class<? extends Sidebar>) clazz;
+ } else {
+ LOG.warn("{} does not extend {}, ignoring...", clazz.getName(), Sidebar.class.getName());
+ }
+ } catch (ClassNotFoundException e) {
+ LOG.error("While looking for class identified by property 'sidebar'", e);
+ }
+ }
+
+ public UserFormLayoutInfo getCustomFormLayout() {
+ return customFormLayout;
+ }
+
+ public Class<? extends Sidebar> getSidebar() {
+ return sidebar;
}
@Override
@@ -418,7 +460,15 @@
setUseCompression(useGZIPCompression);
}
- protected static Class<? extends WebPage> getSignInPageClass() {
+ public Class<? extends BasePage> getPageClass(final String key) {
+ return pageClasses.get(key);
+ }
+
+ public Class<? extends BasePage> getPageClass(final String key, final Class<? extends BasePage> defaultValue) {
+ return pageClasses.getOrDefault(key, defaultValue);
+ }
+
+ protected Class<? extends WebPage> getSignInPageClass() {
return Login.class;
}
@@ -458,12 +508,4 @@
return maxWaitTime;
}
- public Map<String, CustomAttributesInfo> getCustomFormAttributes() {
- return customFormAttributes;
- }
-
- public void setCustomFormAttributes(final Map<String, CustomAttributesInfo> customFormAttributes) {
- this.customFormAttributes.clear();
- this.customFormAttributes.putAll(customFormAttributes);
- }
}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/assets/SyncopeEnduserCss.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/assets/SyncopeEnduserCss.java
deleted file mode 100644
index bc25789..0000000
--- a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/assets/SyncopeEnduserCss.java
+++ /dev/null
@@ -1,49 +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.enduser.assets;
-
-import de.agilecoders.wicket.core.Bootstrap;
-import java.util.ArrayList;
-import java.util.List;
-import org.apache.wicket.markup.head.CssHeaderItem;
-import org.apache.wicket.markup.head.HeaderItem;
-import org.apache.wicket.request.resource.CssResourceReference;
-
-public class SyncopeEnduserCss extends CssResourceReference {
-
- private static final long serialVersionUID = 7244898174745686253L;
-
- /**
- * Singleton instance of this reference.
- */
- public static final SyncopeEnduserCss INSTANCE = new SyncopeEnduserCss();
-
- public SyncopeEnduserCss() {
- super(SyncopeEnduserCss.class, "css/syncopeEnduser.css");
- }
-
- @Override
- public List<HeaderItem> getDependencies() {
- final List<HeaderItem> dependencies = new ArrayList<>();
- dependencies.add(CssHeaderItem.forReference(Bootstrap.getSettings().getCssResourceReference()));
- dependencies.addAll(super.getDependencies());
- return dependencies;
- }
-
-}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/BaseExtPage.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/commons/EnduserConstants.java
similarity index 60%
rename from client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/BaseExtPage.java
rename to client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/commons/EnduserConstants.java
index ace1d2f..abdf652 100644
--- a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/BaseExtPage.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/commons/EnduserConstants.java
@@ -16,19 +16,23 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.syncope.client.enduser.pages;
+package org.apache.syncope.client.enduser.commons;
-import org.apache.wicket.request.mapper.parameter.PageParameters;
+public final class EnduserConstants {
-public abstract class BaseExtPage extends BaseEnduserWebPage {
+ public static final String STATUS = "status";
- private static final long serialVersionUID = 4627828052717627159L;
+ public static final String SUCCESS = "success";
- public BaseExtPage() {
- super();
- }
+ public static final String LANDING_PAGE = "landingPage";
- public BaseExtPage(final PageParameters parameters) {
- super(parameters);
+ public static final String CONTENT_PANEL = "contentPanel";
+
+ public static final String SELF_ALLOWED = "selfRegistration.allowed";
+
+ public static final String PAGE_TITLE = "pageTitle";
+
+ private EnduserConstants() {
+ // private constructor for static utility class
}
}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/init/ClassPathScanImplementationLookup.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/init/ClassPathScanImplementationLookup.java
index c89afff..6f1e334 100644
--- a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/init/ClassPathScanImplementationLookup.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/init/ClassPathScanImplementationLookup.java
@@ -24,8 +24,7 @@
import java.util.List;
import java.util.Objects;
import org.apache.commons.lang3.ArrayUtils;
-import org.apache.syncope.client.enduser.pages.BaseEnduserWebPage;
-import org.apache.syncope.client.enduser.pages.BaseExtPage;
+import org.apache.syncope.client.enduser.pages.BasePage;
import org.apache.syncope.client.ui.commons.annotations.BinaryPreview;
import org.apache.syncope.client.ui.commons.annotations.ExtPage;
import org.apache.syncope.client.ui.commons.annotations.Resource;
@@ -50,9 +49,7 @@
private List<Class<? extends BinaryPreviewer>> previewers;
- private List<Class<? extends BaseExtPage>> extPages;
-
- private List<Class<? extends BaseEnduserWebPage>> pages;
+ private List<Class<? extends BasePage>> extPages;
/**
* This method can be overridden by subclasses to customize classpath scan.
@@ -63,9 +60,8 @@
return DEFAULT_BASE_PACKAGE;
}
- @SuppressWarnings("unchecked")
+ @SuppressWarnings({ "unchecked", "unchecked" })
public void load() {
- pages = new ArrayList<>();
previewers = new ArrayList<>();
extPages = new ArrayList<>();
ssoLoginFormPanels = new ArrayList<>();
@@ -73,10 +69,9 @@
ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false);
scanner.addIncludeFilter(new AssignableTypeFilter(AbstractResource.class));
- scanner.addIncludeFilter(new AssignableTypeFilter(BaseExtPage.class));
+ scanner.addIncludeFilter(new AssignableTypeFilter(BasePage.class));
scanner.addIncludeFilter(new AssignableTypeFilter(BaseSSOLoginFormPanel.class));
scanner.addIncludeFilter(new AssignableTypeFilter(BinaryPreviewer.class));
- scanner.addIncludeFilter(new AssignableTypeFilter(BaseEnduserWebPage.class));
scanner.findCandidateComponents(getBasePackage()).forEach(bd -> {
try {
@@ -84,9 +79,9 @@
ClassUtils.getDefaultClassLoader());
boolean isAbstractClazz = Modifier.isAbstract(clazz.getModifiers());
if (!isAbstractClazz) {
- if (BaseExtPage.class.isAssignableFrom(clazz)) {
+ if (BasePage.class.isAssignableFrom(clazz)) {
if (clazz.isAnnotationPresent(ExtPage.class)) {
- extPages.add((Class<? extends BaseExtPage>) clazz);
+ extPages.add((Class<? extends BasePage>) clazz);
} else {
LOG.error("Could not find annotation {} in {}, ignoring",
ExtPage.class.getName(), clazz.getName());
@@ -102,8 +97,6 @@
previewers.add((Class<? extends BinaryPreviewer>) clazz);
} else if (BaseSSOLoginFormPanel.class.isAssignableFrom(clazz)) {
ssoLoginFormPanels.add((Class<? extends BaseSSOLoginFormPanel>) clazz);
- } else if (BaseEnduserWebPage.class.isAssignableFrom(clazz)) {
- pages.add((Class<? extends BaseEnduserWebPage>) clazz);
}
}
} catch (Throwable t) {
@@ -114,8 +107,6 @@
ssoLoginFormPanels = Collections.unmodifiableList(ssoLoginFormPanels);
- pages = Collections.unmodifiableList(pages);
-
LOG.debug("Binary previewers found: {}", previewers);
LOG.debug("Extension pages found: {}", extPages);
LOG.debug("SSO Login pages found: {}", ssoLoginFormPanels);
@@ -144,11 +135,7 @@
return this.ssoLoginFormPanels;
}
- public List<Class<? extends BaseExtPage>> getExtPageClasses() {
+ public List<Class<? extends BasePage>> getExtPageClasses() {
return extPages;
}
-
- public List<Class<? extends BaseEnduserWebPage>> getPageClasses() {
- return pages;
- }
}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/layout/AnyLayoutUtils.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/layout/AnyLayoutUtils.java
deleted file mode 100644
index 5739f02..0000000
--- a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/layout/AnyLayoutUtils.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.enduser.layout;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import java.io.IOException;
-import java.lang.reflect.InvocationTargetException;
-import java.util.List;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.syncope.client.enduser.SyncopeEnduserSession;
-import org.apache.syncope.client.ui.commons.wizards.ModalPanelBuilder;
-import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
-import org.apache.syncope.common.lib.to.UserTO;
-import org.apache.syncope.common.lib.types.AnyTypeKind;
-import org.apache.wicket.PageReference;
-
-/**
- * Utility methods for dealing with form layout information.
- */
-public final class AnyLayoutUtils {
-
- private static final ObjectMapper MAPPER;
-
- private static final String DEFAULT_USER_FORM_LAYOUT_INFO;
-
- static {
- MAPPER = new ObjectMapper();
- try {
- DEFAULT_USER_FORM_LAYOUT_INFO = MAPPER.writeValueAsString(new UserFormLayoutInfo());
- } catch (IOException e) {
- throw new IllegalArgumentException("While generating default enduser layout info for "
- + SyncopeEnduserSession.get().getSelfTO().getUsername(), e);
- }
- }
-
- public static String getDefaultValue() {
- return DEFAULT_USER_FORM_LAYOUT_INFO;
- }
-
- public static UserFormLayoutInfo fromJsonString(final String content) {
- try {
- return MAPPER.readValue(content, UserFormLayoutInfo.class);
- } catch (IOException e) {
- throw new IllegalArgumentException("While parsing console layout info for "
- + SyncopeEnduserSession.get().getSelfTO().getUsername(), e);
- }
- }
-
- public static String defaultConsoleLayoutInfoIfEmpty(final String content) {
- String result;
-
- if (StringUtils.isBlank(content)) {
- try {
- ObjectNode tree = MAPPER.createObjectNode();
-
- tree.set(AnyTypeKind.USER.name(), MAPPER.valueToTree(new UserFormLayoutInfo()));
-
- result = MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(tree);
- } catch (IOException e) {
- throw new IllegalArgumentException("While generating default console layout info for "
- + SyncopeEnduserSession.get().getSelfTO().getUsername(), e);
- }
- } else {
- try {
- result = MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(MAPPER.readTree(content));
- } catch (IOException e) {
- result = content;
- }
- }
-
- return result;
- }
-
- public static ModalPanelBuilder<AnyWrapper<UserTO>> newUserWizardBuilder(
- final UserTO userTO,
- final List<String> anyTypeClasses,
- final UserFormLayoutInfo userFormLayoutInfo,
- final PageReference pageRef) {
-
- try {
- return userFormLayoutInfo.getFormClass().getConstructor(
- userTO.getClass(), // previous
- userTO.getClass(), // actual
- List.class,
- userFormLayoutInfo.getClass(),
- pageRef.getClass()).
- newInstance(null, userTO, anyTypeClasses, userFormLayoutInfo, pageRef);
-
- } catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException
- | IllegalArgumentException | InvocationTargetException e) {
- throw new IllegalArgumentException(
- "Could not instantiate " + userFormLayoutInfo.getFormClass().getName(), e);
- }
- }
-
- private AnyLayoutUtils() {
- // private constructor for static utility class
- }
-}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/layout/CustomizationOption.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/layout/CustomizationOption.java
index c716f07..0fe471f 100644
--- a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/layout/CustomizationOption.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/layout/CustomizationOption.java
@@ -30,9 +30,6 @@
private List<String> defaultValues = new ArrayList<>();
- public CustomizationOption() {
- }
-
public boolean isReadonly() {
return readonly;
}
@@ -48,15 +45,4 @@
public void setDefaultValues(final List<String> defaultValues) {
this.defaultValues = defaultValues;
}
-
- public CustomizationOption readonly(final Boolean value) {
- this.readonly = value;
- return this;
- }
-
- public CustomizationOption defaultValues(final List<String> value) {
- this.defaultValues = value;
- return this;
- }
-
}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/layout/UserFormLayoutInfo.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/layout/UserFormLayoutInfo.java
index 477c1d1..0c81adc 100644
--- a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/layout/UserFormLayoutInfo.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/layout/UserFormLayoutInfo.java
@@ -20,10 +20,10 @@
import java.util.HashMap;
import java.util.Map;
-import org.apache.syncope.client.enduser.wizards.any.UserWizardBuilder;
+import org.apache.syncope.client.enduser.panels.UserFormPanel;
import org.apache.syncope.client.ui.commons.layout.AbstractAnyFormBaseLayout;
-import org.apache.syncope.client.ui.commons.layout.UserForm;
import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.client.ui.commons.layout.UserForm;
public class UserFormLayoutInfo extends AbstractAnyFormBaseLayout<UserTO, UserForm> {
@@ -37,6 +37,8 @@
private boolean passwordManagement = true;
+ private boolean detailsManagement = true;
+
public Map<String, CustomizationOption> getWhichPlainAttrs() {
return whichPlainAttrs;
}
@@ -51,7 +53,7 @@
@Override
protected Class<? extends UserForm> getDefaultFormClass() {
- return UserWizardBuilder.class;
+ return UserFormPanel.class;
}
public boolean isPasswordManagement() {
@@ -61,4 +63,12 @@
public void setPasswordManagement(final boolean passwordManagement) {
this.passwordManagement = passwordManagement;
}
+
+ public boolean isDetailsManagement() {
+ return detailsManagement;
+ }
+
+ public void setDetailsManagement(final boolean detailsManagement) {
+ this.detailsManagement = detailsManagement;
+ }
}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/markup/html/form/AjaxDownload.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/markup/html/form/AjaxDownload.java
deleted file mode 100644
index 8e1367a..0000000
--- a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/markup/html/form/AjaxDownload.java
+++ /dev/null
@@ -1,88 +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.enduser.markup.html.form;
-
-import java.time.Duration;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.syncope.client.ui.commons.HttpResourceStream;
-import org.apache.syncope.client.ui.commons.MIMETypesLoader;
-import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.behavior.AbstractAjaxBehavior;
-import org.apache.wicket.request.handler.resource.ResourceStreamRequestHandler;
-import org.apache.wicket.request.resource.ContentDisposition;
-import org.apache.wicket.spring.injection.annot.SpringBean;
-
-public abstract class AjaxDownload extends AbstractAjaxBehavior {
-
- private static final long serialVersionUID = 7203445884857810583L;
-
- @SpringBean
- private MIMETypesLoader mimeTypesLoader;
-
- private final String name;
-
- private String fileKey;
-
- private String mimeType;
-
- private final boolean addAntiCache;
-
- public AjaxDownload(final String name, final boolean addAntiCache) {
- super();
- this.name = name;
- this.addAntiCache = addAntiCache;
- }
-
- public AjaxDownload(final String name, final String fileKey, final String mimeType, final boolean addAntiCache) {
- this(name, addAntiCache);
- this.fileKey = fileKey;
- this.mimeType = mimeType;
- }
-
- public void initiate(final AjaxRequestTarget target) {
-
- String url = getCallbackUrl().toString();
- if (addAntiCache) {
- url = url + (url.contains("?") ? "&" : "?");
- url = url + "antiCache=" + System.currentTimeMillis();
- }
- target.appendJavaScript("setTimeout(\"window.location.href='" + url + "'\", 100);");
- }
-
- @Override
- public void onRequest() {
- HttpResourceStream stream = getResourceStream();
- ResourceStreamRequestHandler handler = new ResourceStreamRequestHandler(stream);
- String key = StringUtils.isNotBlank(fileKey) ? fileKey + '_' : "";
- String ext = "";
- if (StringUtils.isNotBlank(mimeType)) {
- String extByMimeType = mimeTypesLoader.getFileExt(mimeType);
- ext = StringUtils.isBlank(extByMimeType) ? ".bin" : ('.' + extByMimeType);
- }
- String fileName = key + (stream.getFilename() == null ? name : stream.getFilename()) + ext;
-
- handler.setFileName(fileName);
- handler.setContentDisposition(ContentDisposition.ATTACHMENT);
- handler.setCacheDuration(Duration.ZERO);
- getComponent().getRequestCycle().scheduleRequestHandlerAfterCurrent(handler);
- }
-
- protected abstract HttpResourceStream getResourceStream();
-
-}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/markup/html/form/BinaryFieldPanel.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/markup/html/form/BinaryFieldPanel.java
index 512283d..f8d88a2 100644
--- a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/markup/html/form/BinaryFieldPanel.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/markup/html/form/BinaryFieldPanel.java
@@ -30,17 +30,19 @@
import java.util.Base64;
import java.util.Locale;
import java.util.Optional;
+import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.apache.commons.lang3.StringUtils;
-import org.apache.syncope.client.ui.commons.HttpResourceStream;
import org.apache.syncope.client.enduser.SyncopeWebApplication;
import org.apache.syncope.client.enduser.SyncopeEnduserSession;
import org.apache.syncope.client.enduser.commons.PreviewUtils;
import org.apache.syncope.client.ui.commons.Constants;
-import org.apache.syncope.client.ui.commons.markup.html.form.BaseBinaryFieldPanel;
+import org.apache.syncope.client.ui.commons.HttpResourceStream;
import org.apache.syncope.client.ui.commons.markup.html.form.FieldPanel;
import org.apache.syncope.client.ui.commons.markup.html.form.preview.BinaryPreviewer;
+import org.apache.syncope.client.ui.commons.markup.html.form.BaseBinaryFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.BinaryFieldDownload;
import org.apache.syncope.client.ui.commons.pages.BaseWebPage;
import org.apache.syncope.client.ui.commons.rest.ResponseHolder;
import org.apache.wicket.Component;
@@ -82,7 +84,7 @@
private final BootstrapFileInputField fileUpload;
- private final AjaxDownload fileDownload;
+ private final BinaryFieldDownload fileDownload;
private final BinaryPreviewer previewer;
@@ -100,6 +102,7 @@
final IModel<String> model,
final String mimeType,
final String fileKey) {
+
super(id, name, model);
this.model = model;
this.fileKey = fileKey;
@@ -122,7 +125,7 @@
public void renderHead(final IHeaderResponse response) {
if (previewer == null) {
FileinputJsReference.INSTANCE.renderHead(response);
- final JQuery fileinputJS = $(fileUpload).chain(new IFunction() {
+ JQuery fileinputJS = $(fileUpload).chain(new IFunction() {
private static final long serialVersionUID = -2285418135375523652L;
@@ -150,7 +153,7 @@
uploadForm.add(new Label("preview", StringUtils.isBlank(mimeType) ? StringUtils.EMPTY : '(' + mimeType + ')'));
- fileDownload = new AjaxDownload(name, fileKey, mimeType, true) {
+ fileDownload = new BinaryFieldDownload(name, fileKey, mimeType, true) {
private static final long serialVersionUID = 7203445884857810583L;
@@ -185,10 +188,7 @@
if (!Locale.ENGLISH.getLanguage().equals(language)) {
config.withLocale(language);
}
-
fileUpload = new BootstrapFileInputField("fileUpload", new ListModel<>(new ArrayList<>()), config);
- fileUpload.setOutputMarkupId(true);
-
fileUpload.add(new AjaxFormSubmitBehavior(Constants.ON_CHANGE) {
private static final long serialVersionUID = -1107858522700306810L;
@@ -253,11 +253,13 @@
private Response buildResponse() {
return Response.ok(new ByteArrayInputStream(Base64.getMimeDecoder().decode(getModelObject()))).
- type(StringUtils.isBlank(mimeType) ? MediaType.APPLICATION_OCTET_STREAM : mimeType).build();
+ type(StringUtils.isBlank(mimeType) ? MediaType.APPLICATION_OCTET_STREAM : mimeType).
+ header(HttpHeaders.LOCATION, StringUtils.EMPTY).
+ build();
}
private void changePreviewer(final Component panelPreview) {
- final Fragment fragment = new Fragment("panelPreview", "previewFragment", container);
+ Fragment fragment = new Fragment("panelPreview", "previewFragment", container);
fragment.add(panelPreview);
container.addOrReplace(fragment);
uploadForm.addOrReplace(container);
@@ -297,4 +299,11 @@
protected Integer getMaxUploadFileSizeMB() {
return SyncopeWebApplication.get().getMaxUploadFileSizeMB();
}
+
+ @Override
+ public FieldPanel<String> setReadOnly(final boolean readOnly) {
+ super.setReadOnly(readOnly);
+ fileUpload.setEnabled(!readOnly);
+ return this;
+ }
}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/navigation/Navbar.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/navigation/Navbar.java
deleted file mode 100644
index fa87444..0000000
--- a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/navigation/Navbar.java
+++ /dev/null
@@ -1,153 +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.enduser.navigation;
-
-import java.util.ArrayList;
-import java.util.List;
-import org.apache.syncope.client.enduser.SyncopeEnduserSession;
-import org.apache.syncope.client.enduser.pages.BaseExtPage;
-import org.apache.syncope.client.enduser.pages.Logout;
-import org.apache.syncope.client.enduser.pages.Self;
-import org.apache.syncope.client.ui.commons.Constants;
-import org.apache.syncope.client.ui.commons.annotations.ExtPage;
-import org.apache.wicket.Component;
-import org.apache.wicket.Page;
-import org.apache.wicket.ajax.AjaxEventBehavior;
-import org.apache.wicket.ajax.AjaxRequestTarget;
-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.behavior.Behavior;
-import org.apache.wicket.markup.ComponentTag;
-import org.apache.wicket.markup.html.WebMarkupContainer;
-import org.apache.wicket.markup.html.WebPage;
-import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.markup.html.link.BookmarkablePageLink;
-import org.apache.wicket.markup.html.list.ListItem;
-import org.apache.wicket.markup.html.list.ListView;
-import org.apache.wicket.markup.html.panel.Panel;
-
-public class Navbar extends Panel {
-
- private static final long serialVersionUID = 1323251762654401168L;
-
- private final ListView<Class<? extends BaseExtPage>> extPages;
-
- private final List<WebMarkupContainer> navbarItems = new ArrayList<>();
-
- public Navbar(final String id, final List<Class<? extends BaseExtPage>> extPageClasses) {
- super(id);
- setOutputMarkupId(true);
-
- WebMarkupContainer detailsLI = new WebMarkupContainer("detailsLI");
- detailsLI.setMarkupId("self");
- navbarItems.add(detailsLI);
- add(detailsLI);
-
- BookmarkablePageLink<Page> detailsLink = new BookmarkablePageLink<>("detailsLILink", Self.class);
- detailsLink.setOutputMarkupId(true);
- detailsLink.add(new Label("detailsLILabel", getString("details")));
- detailsLI.add(detailsLink);
-
- WebMarkupContainer extLI = new WebMarkupContainer("extensionsLI");
- extLI.setOutputMarkupPlaceholderTag(true);
- extLI.setVisible(!extPageClasses.isEmpty());
- add(extLI);
-
- extPages = new ListView<Class<? extends BaseExtPage>>("extPages", extPageClasses) {
-
- private static final long serialVersionUID = 4949588177564901031L;
-
- @Override
- protected void populateItem(final ListItem<Class<? extends BaseExtPage>> item) {
- WebMarkupContainer extPageLI = new WebMarkupContainer("extPageLI");
- item.add(extPageLI);
- extPageLI.setMarkupId(item.getModelObject().getSimpleName().toLowerCase());
- navbarItems.add(extPageLI);
-
- ExtPage ann = item.getModelObject().getAnnotation(ExtPage.class);
-
- BookmarkablePageLink<Page> extLIPageLink =
- new BookmarkablePageLink<>("extPageLILink", item.getModelObject());
- extLIPageLink.setOutputMarkupId(true);
- extLIPageLink.add(new Label("extPageLabel", ann.label()));
- extPageLI.add(extLIPageLink);
- }
- };
- extPages.setOutputMarkupId(true);
- extPages.setVisible(true);
- extLI.add(extPages);
-
- WebMarkupContainer logoLinkWmc = new WebMarkupContainer("logoIcon");
- logoLinkWmc.add(new AjaxEventBehavior("click") {
-
- private static final long serialVersionUID = -4255753643957306394L;
-
- @Override
- protected void onEvent(final AjaxRequestTarget target) {
- setResponsePage(getApplication().getHomePage());
- }
- });
- add(logoLinkWmc);
-
- @SuppressWarnings("unchecked")
- final Class<? extends WebPage> beforeLogout = (Class<? extends WebPage>) SyncopeEnduserSession.get().
- getAttribute(Constants.BEFORE_LOGOUT_PAGE);
- if (beforeLogout == null) {
- add(new BookmarkablePageLink<>("logout", Logout.class));
- } else {
- add(new AjaxLink<Page>("logout") {
-
- private static final long serialVersionUID = -4889563567201424183L;
-
- @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);
- }
- });
- }
- }
-
- public ListView<Class<? extends BaseExtPage>> getExtPages() {
- return extPages;
- }
-
- public void setActiveNavItem(final String id) {
- navbarItems.stream().
- filter(containingLI -> containingLI.getMarkupId().equals(id)).findFirst().
- ifPresent(found -> found.add(new Behavior() {
-
- private static final long serialVersionUID = -5775607340182293596L;
-
- @Override
- public void onComponentTag(final Component component, final ComponentTag tag) {
- tag.put("class", "active");
- }
- }));
- }
-}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/AbstractChangePassword.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/AbstractChangePassword.java
new file mode 100644
index 0000000..5944754
--- /dev/null
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/AbstractChangePassword.java
@@ -0,0 +1,89 @@
+/*
+ * 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.enduser.pages;
+
+import org.apache.syncope.client.enduser.SyncopeEnduserSession;
+import org.apache.syncope.client.enduser.SyncopeWebApplication;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxPasswordFieldPanel;
+import org.apache.syncope.client.enduser.panels.ChangePasswordPanel;
+import org.apache.syncope.client.ui.commons.Constants;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.wicket.AttributeModifier;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
+
+public abstract class AbstractChangePassword extends BasePage {
+
+ private static final long serialVersionUID = 5889157642852559004L;
+
+ private static final String CHANGE_PASSWORD = "page.changePassword";
+
+ public AbstractChangePassword(final PageParameters parameters) {
+ super(parameters, CHANGE_PASSWORD);
+
+ WebMarkupContainer content = new WebMarkupContainer("content");
+ content.setOutputMarkupId(true);
+ contentWrapper.add(content);
+
+ ChangePasswordPanel changePasswordPanel = getPasswordPanel();
+ content.add(changePasswordPanel);
+ content.add(new AttributeModifier("style", "height: \"100%\""));
+ }
+
+ protected ChangePasswordPanel getPasswordPanel() {
+ ChangePasswordPanel changePasswordPanel = new ChangePasswordPanel("changePasswordPanel", notificationPanel) {
+
+ private static final long serialVersionUID = 5195544218030499386L;
+
+ @Override
+ protected void doSubmit(final AjaxRequestTarget target, final AjaxPasswordFieldPanel passwordField) {
+ boolean checked = true;
+ if (SyncopeWebApplication.get().isCaptchaEnabled()) {
+ checked = captcha.check();
+ }
+ if (!checked) {
+ SyncopeEnduserSession.get().error(getString(Constants.CAPTCHA_ERROR));
+ getNotificationPanel().refresh(target);
+ } else {
+ doPwdSubmit(target, passwordField);
+ }
+ }
+
+ @Override
+ protected void doCancel() {
+ doPwdCancel();
+ }
+
+ @Override
+ protected UserTO getLoggedUser() {
+ return getPwdLoggedUser();
+ }
+ };
+
+ changePasswordPanel.setOutputMarkupId(true);
+ return changePasswordPanel;
+ }
+
+ protected abstract void doPwdSubmit(AjaxRequestTarget target, AjaxPasswordFieldPanel passwordField);
+
+ protected abstract void doPwdCancel();
+
+ protected abstract UserTO getPwdLoggedUser();
+}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/BaseEnduserWebPage.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/BaseEnduserWebPage.java
deleted file mode 100644
index e7503bf..0000000
--- a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/BaseEnduserWebPage.java
+++ /dev/null
@@ -1,48 +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.enduser.pages;
-
-import org.apache.syncope.client.enduser.init.ClassPathScanImplementationLookup;
-import org.apache.syncope.client.enduser.navigation.Navbar;
-import org.apache.syncope.client.ui.commons.pages.BaseWebPage;
-import org.apache.wicket.request.mapper.parameter.PageParameters;
-import org.apache.wicket.spring.injection.annot.SpringBean;
-
-public class BaseEnduserWebPage extends BaseWebPage {
-
- private static final long serialVersionUID = 5760583420031293480L;
-
- protected final Navbar navbar;
-
- @SpringBean
- protected ClassPathScanImplementationLookup lookup;
-
- public BaseEnduserWebPage() {
- this(null);
-
- body.add(navbar);
- }
-
- public BaseEnduserWebPage(final PageParameters parameters) {
- super(parameters);
-
- navbar = new Navbar("navbar", lookup.getExtPageClasses());
- body.add(navbar);
- }
-}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/BasePage.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/BasePage.java
new file mode 100644
index 0000000..eb238da
--- /dev/null
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/BasePage.java
@@ -0,0 +1,161 @@
+/*
+ * 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.enduser.pages;
+
+import java.io.Serializable;
+import java.lang.reflect.InvocationTargetException;
+import java.util.List;
+import org.apache.syncope.client.enduser.SyncopeWebApplication;
+import org.apache.syncope.client.enduser.SyncopeEnduserSession;
+import org.apache.syncope.client.enduser.commons.EnduserConstants;
+import org.apache.syncope.client.enduser.init.ClassPathScanImplementationLookup;
+import org.apache.syncope.client.enduser.wicket.markup.head.MetaHeaderItem;
+import org.apache.syncope.client.ui.commons.BaseSession;
+import org.apache.syncope.client.ui.commons.Constants;
+import org.apache.syncope.client.enduser.panels.Sidebar;
+import org.apache.syncope.client.ui.commons.pages.BaseWebPage;
+import org.apache.wicket.AttributeModifier;
+import org.apache.wicket.Page;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.Session;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+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.behavior.AttributeAppender;
+import org.apache.wicket.markup.head.HeaderItem;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.WebPage;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.link.BookmarkablePageLink;
+import org.apache.wicket.model.ResourceModel;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
+import org.apache.wicket.spring.injection.annot.SpringBean;
+
+public class BasePage extends BaseWebPage {
+
+ private static final long serialVersionUID = 1571997737305598502L;
+
+ @SpringBean
+ private ClassPathScanImplementationLookup lookup;
+
+ protected static final HeaderItem META_IE_EDGE = new MetaHeaderItem("X-UA-Compatible", "IE=edge");
+
+ protected final Sidebar sidebar;
+
+ protected final WebMarkupContainer contentWrapper;
+
+ protected final AjaxLink<Void> collapse;
+
+ public BasePage() {
+ this(null, null);
+ }
+
+ public BasePage(final PageParameters parameters, final String name) {
+ super(parameters);
+
+ Serializable leftMenuCollapse = SyncopeEnduserSession.get().getAttribute(Constants.MENU_COLLAPSE);
+ if ((leftMenuCollapse instanceof Boolean) && ((Boolean) leftMenuCollapse)) {
+ body.add(new AttributeAppender("class", " sidebar-collapse"));
+ }
+
+ // sidebar
+ Class<? extends Sidebar> clazz = SyncopeWebApplication.get().getSidebar();
+
+ try {
+ sidebar = clazz.getConstructor(
+ String.class,
+ PageReference.class,
+ List.class).
+ newInstance("sidebar", getPageReference(), lookup.getExtPageClasses());
+ } catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException
+ | IllegalArgumentException | InvocationTargetException e) {
+ throw new IllegalArgumentException("Could not instantiate " + clazz.getName(), e);
+ }
+
+ sidebar.setOutputMarkupPlaceholderTag(true);
+ body.add(sidebar);
+
+ // contentWrapper
+ contentWrapper = new WebMarkupContainer("contentWrapper");
+ contentWrapper.setOutputMarkupPlaceholderTag(true);
+ body.add(contentWrapper);
+
+ //pageTitle
+ addPageTitle(name);
+
+ // collapse
+ collapse = new AjaxLink<Void>("collapse") {
+
+ private static final long serialVersionUID = -7978723352517770644L;
+
+ @Override
+ public void onClick(final AjaxRequestTarget target) {
+ Session.get().setAttribute(Constants.MENU_COLLAPSE,
+ Session.get().getAttribute(Constants.MENU_COLLAPSE) == null
+ ? true
+ : !(Boolean) Session.get().getAttribute(Constants.MENU_COLLAPSE));
+ }
+ };
+ collapse.setOutputMarkupPlaceholderTag(true);
+ body.add(collapse);
+
+ @SuppressWarnings("unchecked")
+ Class<? extends WebPage> beforeLogout = (Class<? extends WebPage>) Session.get().
+ getAttribute(Constants.BEFORE_LOGOUT_PAGE);
+ if (beforeLogout == null) {
+ body.add(new BookmarkablePageLink<>("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);
+ }
+ });
+ }
+ }
+
+ protected void addPageTitle(final String title) {
+ contentWrapper.addOrReplace(new Label(EnduserConstants.PAGE_TITLE, new ResourceModel(title, title)));
+ }
+
+ protected void disableSidebar() {
+ sidebar.setVisible(false);
+ collapse.setVisible(false);
+ contentWrapper.add(new AttributeModifier("style", "margin-left: 0px"));
+ }
+
+ protected void setDomain(final PageParameters parameters) {
+ if (parameters != null && !parameters.get("domain").isEmpty()) {
+ BaseSession.class.cast(Session.get()).setDomain(parameters.get("domain").toString());
+ }
+ }
+}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/Dashboard.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/Dashboard.java
new file mode 100644
index 0000000..c99c789
--- /dev/null
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/Dashboard.java
@@ -0,0 +1,45 @@
+/*
+ * 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.enduser.pages;
+
+import org.apache.syncope.client.enduser.widgets.UserProfileWidget;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
+
+public class Dashboard extends BasePage {
+
+ private static final long serialVersionUID = -1100228004207271270L;
+
+ protected static final String HOME = "home";
+
+ protected final WebMarkupContainer content;
+
+ public Dashboard(final PageParameters parameters) {
+ super(parameters, HOME);
+
+ content = new WebMarkupContainer("content");
+ content.setOutputMarkupId(true);
+
+ UserProfileWidget userProfileWidget = new UserProfileWidget("userProfileInfo");
+ userProfileWidget.setOutputMarkupId(true);
+ content.add(userProfileWidget);
+
+ contentWrapper.add(content);
+ }
+}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/EditChangePassword.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/EditChangePassword.java
new file mode 100644
index 0000000..fb54b7a
--- /dev/null
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/EditChangePassword.java
@@ -0,0 +1,80 @@
+/*
+ * 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.enduser.pages;
+
+import org.apache.syncope.client.enduser.SyncopeWebApplication;
+import org.apache.syncope.client.enduser.SyncopeEnduserSession;
+import org.apache.syncope.client.enduser.commons.EnduserConstants;
+import org.apache.syncope.client.enduser.rest.UserSelfRestClient;
+import org.apache.syncope.client.ui.commons.Constants;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxPasswordFieldPanel;
+import org.apache.syncope.common.lib.request.PasswordPatch;
+import org.apache.syncope.common.lib.request.UserUR;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
+
+public class EditChangePassword extends AbstractChangePassword {
+
+ private static final long serialVersionUID = -537205681762708502L;
+
+ private final UserSelfRestClient userSelfRestClient = new UserSelfRestClient();
+
+ public EditChangePassword(final PageParameters parameters) {
+ super(parameters);
+ }
+
+ @Override
+ protected void doPwdSubmit(final AjaxRequestTarget target, final AjaxPasswordFieldPanel passwordField) {
+ PageParameters parameters = new PageParameters();
+ try {
+ UserTO userTO = getPwdLoggedUser();
+
+ UserUR req = new UserUR();
+ req.setKey(userTO.getKey());
+ req.setPassword(new PasswordPatch.Builder().
+ value(passwordField.getModelObject()).onSyncope(true).resources(userTO.getResources()).build());
+ userSelfRestClient.update(userTO.getETagValue(), req);
+
+ parameters.add(EnduserConstants.STATUS, Constants.OPERATION_SUCCEEDED);
+ parameters.add(Constants.NOTIFICATION_TITLE_PARAM, getString("self.pwd.change.success.msg"));
+ parameters.add(Constants.NOTIFICATION_MSG_PARAM, getString("self.pwd.change.success"));
+ SyncopeEnduserSession.get().success(getString(Constants.OPERATION_SUCCEEDED));
+ parameters.add(
+ EnduserConstants.LANDING_PAGE,
+ SyncopeWebApplication.get().getPageClass("profile", Dashboard.class).getName());
+ setResponsePage(SelfResult.class, parameters);
+ } catch (Exception e) {
+ LOG.error("While changing password for {}",
+ SyncopeEnduserSession.get().getSelfTO().getUsername(), e);
+ SyncopeEnduserSession.get().onException(e);
+ notificationPanel.refresh(target);
+ }
+ }
+
+ @Override
+ protected UserTO getPwdLoggedUser() {
+ return SyncopeEnduserSession.get().getSelfTO(true);
+ }
+
+ @Override
+ protected void doPwdCancel() {
+ setResponsePage(getApplication().getHomePage());
+ }
+}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/EditSecurityQuestion.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/EditSecurityQuestion.java
new file mode 100644
index 0000000..3a63cad
--- /dev/null
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/EditSecurityQuestion.java
@@ -0,0 +1,210 @@
+/*
+ * 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.enduser.pages;
+
+import java.util.List;
+import java.util.stream.Collectors;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.enduser.SyncopeEnduserSession;
+import org.apache.syncope.client.enduser.SyncopeWebApplication;
+import org.apache.syncope.client.enduser.commons.EnduserConstants;
+import org.apache.syncope.client.enduser.panels.captcha.CaptchaPanel;
+import org.apache.syncope.client.enduser.rest.SecurityQuestionRestClient;
+import org.apache.syncope.client.enduser.rest.UserSelfRestClient;
+import org.apache.syncope.client.ui.commons.Constants;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.FieldPanel;
+import org.apache.syncope.client.ui.commons.panels.CardPanel;
+import org.apache.syncope.common.lib.request.StringReplacePatchItem;
+import org.apache.syncope.common.lib.request.UserUR;
+import org.apache.syncope.common.lib.to.SecurityQuestionTO;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.wicket.ajax.AjaxEventBehavior;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.markup.html.form.AjaxButton;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.form.Button;
+import org.apache.wicket.markup.html.form.IChoiceRenderer;
+import org.apache.wicket.markup.html.form.StatelessForm;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.model.PropertyModel;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
+
+public class EditSecurityQuestion extends BasePage {
+
+ private static final long serialVersionUID = -537205681762708502L;
+
+ private static final String EDIT_SECURITY_QUESTION = "page.editSecurityQuestion";
+
+ private final UserSelfRestClient userSelfRestClient = new UserSelfRestClient();
+
+ private final AjaxDropDownChoicePanel<String> securityQuestion;
+
+ private final FieldPanel<String> securityAnswer;
+
+ private final UserTO userTO;
+
+ public EditSecurityQuestion(final PageParameters parameters) {
+ super(parameters, EDIT_SECURITY_QUESTION);
+
+ userTO = SyncopeEnduserSession.get().getSelfTO(true);
+
+ WebMarkupContainer content = new WebMarkupContainer("content");
+ content.setOutputMarkupId(true);
+ contentWrapper.add(content);
+
+ StatelessForm<Void> form = new StatelessForm<>("securityQuestionForm");
+ form.setOutputMarkupId(true);
+ content.add(form);
+
+ securityQuestion = new AjaxDropDownChoicePanel<>("securityQuestion",
+ "securityQuestion", new PropertyModel<>(userTO, "securityQuestion"));
+ securityQuestion.setNullValid(true);
+
+ List<SecurityQuestionTO> securityQuestions = SecurityQuestionRestClient.list();
+ securityQuestion.setChoices(securityQuestions.stream().
+ map(SecurityQuestionTO::getKey).collect(Collectors.toList()));
+ securityQuestion.setChoiceRenderer(new IChoiceRenderer<String>() {
+
+ private static final long serialVersionUID = -4421146737845000747L;
+
+ @Override
+ public Object getDisplayValue(final String value) {
+ return securityQuestions.stream().filter(sq -> value.equals(sq.getKey())).
+ map(SecurityQuestionTO::getContent).findFirst().orElse(null);
+ }
+
+ @Override
+ public String getIdValue(final String value, final int index) {
+ return value;
+ }
+
+ @Override
+ public String getObject(final String id, final IModel<? extends List<? extends String>> choices) {
+ return id;
+ }
+ });
+
+ securityQuestion.add(new AjaxEventBehavior(Constants.ON_CHANGE) {
+
+ private static final long serialVersionUID = 192359260308762078L;
+
+ @Override
+ protected void onEvent(final AjaxRequestTarget target) {
+ securityAnswer.setEnabled(StringUtils.isNotBlank(securityQuestion.getModelObject()));
+ target.add(securityAnswer);
+ }
+ });
+
+ form.add(securityQuestion);
+
+ securityAnswer = new AjaxTextFieldPanel("securityAnswer", "securityAnswer",
+ new PropertyModel<>(userTO, "securityAnswer"), false);
+ form.add(securityAnswer.setOutputMarkupId(true).setOutputMarkupPlaceholderTag(true).
+ setEnabled(StringUtils.isNotBlank(securityQuestion.getModelObject())));
+
+ CaptchaPanel<Void> captcha = new CaptchaPanel<>(EnduserConstants.CONTENT_PANEL);
+ captcha.setOutputMarkupPlaceholderTag(true);
+
+ form.add(new CardPanel.Builder<CaptchaPanel<Void>>()
+ .setName("captcha")
+ .setComponent(captcha)
+ .isVisible(SyncopeWebApplication.get().isCaptchaEnabled()).build("captchaPanelCard"));
+
+ AjaxButton submitButton = new AjaxButton("submit", new Model<>(getString("submit"))) {
+
+ private static final long serialVersionUID = 429178684321093953L;
+
+ @Override
+ protected void onSubmit(final AjaxRequestTarget target) {
+ if (StringUtils.isBlank(securityQuestion.getModelObject())
+ || StringUtils.isBlank(securityAnswer.getModelObject())) {
+
+ SyncopeEnduserSession.get().error(getString(Constants.CAPTCHA_ERROR));
+ ((BasePage) getPageReference().getPage()).getNotificationPanel().refresh(target);
+ } else {
+ boolean checked = true;
+ if (SyncopeWebApplication.get().isCaptchaEnabled()) {
+ checked = captcha.check();
+ }
+ if (!checked) {
+ SyncopeEnduserSession.get().error(getString(Constants.CAPTCHA_ERROR));
+ ((BasePage) getPageReference().getPage()).getNotificationPanel().refresh(target);
+ } else {
+ PageParameters parameters = new PageParameters();
+ try {
+ UserUR req = new UserUR();
+ req.setKey(userTO.getKey());
+ req.setSecurityQuestion(new StringReplacePatchItem.Builder().
+ value(securityQuestion.getModelObject()).build());
+ req.setSecurityAnswer(new StringReplacePatchItem.Builder().
+ value(securityAnswer.getModelObject()).build());
+ userSelfRestClient.update(userTO.getETagValue(), req);
+
+ parameters.add(EnduserConstants.STATUS, Constants.OPERATION_SUCCEEDED);
+ parameters.add(Constants.NOTIFICATION_TITLE_PARAM,
+ getString("self.securityquestion.change.success"));
+ parameters.add(Constants.NOTIFICATION_MSG_PARAM,
+ getString("self.securityquestion.change.success.msg"));
+ SyncopeEnduserSession.get().success(getString(Constants.OPERATION_SUCCEEDED));
+ } catch (Exception e) {
+ LOG.error("While changing password for {}",
+ SyncopeEnduserSession.get().getSelfTO().getUsername(), e);
+ parameters.add(EnduserConstants.STATUS, Constants.OPERATION_ERROR);
+ parameters.add(Constants.NOTIFICATION_TITLE_PARAM,
+ getString("self.securityquestion.change.error"));
+ parameters.add(Constants.NOTIFICATION_MSG_PARAM,
+ getString("self.securityquestion.change.error.msg"));
+ SyncopeEnduserSession.get().onException(e);
+ notificationPanel.refresh(target);
+ }
+ parameters.add(
+ EnduserConstants.LANDING_PAGE,
+ SyncopeWebApplication.get().getPageClass("profile", Dashboard.class).getName());
+ setResponsePage(SelfResult.class, parameters);
+ }
+ }
+ }
+
+ @Override
+ protected void onError(final AjaxRequestTarget target) {
+ notificationPanel.refresh(target);
+ }
+ };
+ form.add(submitButton);
+
+ form.setDefaultButton(submitButton);
+
+ Button cancel = new Button("cancel") {
+
+ private static final long serialVersionUID = 3669569969172391336L;
+
+ @Override
+ public void onSubmit() {
+ setResponsePage(getApplication().getHomePage());
+ }
+ };
+
+ cancel.setOutputMarkupId(true);
+ cancel.setDefaultFormProcessing(false);
+ form.add(cancel);
+ }
+}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/EditUser.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/EditUser.java
new file mode 100644
index 0000000..341f185
--- /dev/null
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/EditUser.java
@@ -0,0 +1,62 @@
+/*
+ * 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.enduser.pages;
+
+import org.apache.syncope.client.enduser.SyncopeWebApplication;
+import org.apache.syncope.client.enduser.SyncopeEnduserSession;
+import org.apache.syncope.client.enduser.layout.UserFormLayoutInfo;
+import org.apache.syncope.client.enduser.panels.UserFormPanel;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.common.rest.api.service.SyncopeService;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
+
+public class EditUser extends BasePage {
+
+ private static final long serialVersionUID = -1100228004207271270L;
+
+ private static final String EDIT_USER = "page.edituser";
+
+ protected WebMarkupContainer content;
+
+ public EditUser(final PageParameters parameters) {
+ super(parameters, EDIT_USER);
+
+ content = new WebMarkupContainer("content");
+ content.setOutputMarkupId(true);
+ contentWrapper.add(content);
+
+ UserTO userTO = SyncopeEnduserSession.get().getSelfTO(true);
+
+ UserFormPanel editUserPanel = new UserFormPanel(
+ "editUserPanel",
+ userTO,
+ userTO,
+ SyncopeEnduserSession.get().getService(SyncopeService.class).platform().getUserClasses(),
+ buildFormLayout(),
+ getPageReference());
+ editUserPanel.setOutputMarkupId(true);
+ content.add(editUserPanel);
+ }
+
+ protected UserFormLayoutInfo buildFormLayout() {
+ UserFormLayoutInfo customlayoutInfo = SyncopeWebApplication.get().getCustomFormLayout();
+ return customlayoutInfo != null ? customlayoutInfo : new UserFormLayoutInfo();
+ }
+}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/Login.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/Login.java
index c9f9a91..bcc26ad 100644
--- a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/Login.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/Login.java
@@ -22,12 +22,10 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
-import java.util.Locale;
import java.util.stream.Collectors;
import java.util.stream.Stream;
-import org.apache.syncope.client.enduser.SyncopeWebApplication;
import org.apache.syncope.client.enduser.SyncopeEnduserSession;
-import org.apache.syncope.client.enduser.init.ClassPathScanImplementationLookup;
+import org.apache.syncope.client.enduser.SyncopeWebApplication;
import org.apache.syncope.client.ui.commons.BaseLogin;
import org.apache.syncope.client.ui.commons.BaseSession;
import org.apache.wicket.Component;
@@ -35,27 +33,27 @@
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.request.mapper.parameter.PageParameters;
-import org.apache.wicket.spring.injection.annot.SpringBean;
public class Login extends BaseLogin {
- private static final long serialVersionUID = -3422492668689122688L;
-
- @SpringBean
- private ClassPathScanImplementationLookup lookup;
-
- private final BookmarkablePageLink<Void> selfRegistration;
+ private static final long serialVersionUID = 5889157642852559004L;
private final BookmarkablePageLink<Void> selfPwdReset;
+ private final BookmarkablePageLink<Void> selfRegistration;
+
public Login(final PageParameters parameters) {
super(parameters);
- selfRegistration = new BookmarkablePageLink<>("self-registration", Self.class);
- add(selfRegistration.setOutputMarkupId(true));
-
selfPwdReset = new BookmarkablePageLink<>("self-pwd-reset", SelfPasswordReset.class);
- add(selfPwdReset.setOutputMarkupId(true));
+ selfPwdReset.getPageParameters().add("domain", SyncopeEnduserSession.get().getDomain());
+ selfPwdReset.setVisible(SyncopeEnduserSession.get().getPlatformInfo().isPwdResetAllowed());
+ add(selfPwdReset.setOutputMarkupId(true).setOutputMarkupPlaceholderTag(true));
+
+ selfRegistration = new BookmarkablePageLink<>("self-registration", SelfRegistration.class);
+ selfRegistration.getPageParameters().add("domain", SyncopeEnduserSession.get().getDomain());
+ selfRegistration.setVisible(SyncopeEnduserSession.get().getPlatformInfo().isSelfRegAllowed());
+ add(selfRegistration.setOutputMarkupId(true).setOutputMarkupPlaceholderTag(true));
}
@Override
@@ -74,10 +72,10 @@
@Override
protected List<Panel> getSSOLoginFormPanels() {
List<Panel> ssoLoginFormPanels = new ArrayList<>();
- lookup.getSSOLoginFormPanels().forEach(ssoLoginFormPanel -> {
+ SyncopeWebApplication.get().getLookup().getSSOLoginFormPanels().forEach(ssoLoginFormPanel -> {
try {
- ssoLoginFormPanels.add(ssoLoginFormPanel.getConstructor(String.class, BaseSession.class).
- newInstance("ssoLogin", SyncopeEnduserSession.get()));
+ ssoLoginFormPanels.add(ssoLoginFormPanel.getConstructor(String.class, BaseSession.class).newInstance(
+ "ssoLogin", SyncopeEnduserSession.get()));
} catch (Exception e) {
LOG.error("Could not initialize the provided SSO login form panel", e);
}
@@ -96,26 +94,22 @@
}
@Override
- protected List<Locale> getSupportedLocales() {
- return SyncopeWebApplication.SUPPORTED_LOCALES;
- }
+ protected void authenticate(final String username, final String password, final AjaxRequestTarget target)
+ throws AccessControlException {
- @Override
- protected void authenticate(
- final String username,
- final String password,
- final AjaxRequestTarget target) throws AccessControlException {
+ if (SyncopeWebApplication.get().getAnonymousUser().equals(username)
+ || SyncopeWebApplication.get().getAdminUser().equals(username)) {
- if (!SyncopeWebApplication.get().getAdminUser().equalsIgnoreCase(username)
- && !SyncopeWebApplication.get().getAnonymousUser().equalsIgnoreCase(username)
- && SyncopeEnduserSession.get().authenticate(username, password)) {
+ throw new AccessControlException("Illegal username");
+ }
- // user has been authenticated successfully
+ if (SyncopeEnduserSession.get().authenticate(username, password)) {
+ // If login has been called because the user was not yet logged in, than continue to the
+ // original destination, otherwise to the Home page
continueToOriginalDestination();
setResponsePage(getApplication().getHomePage());
} else {
- // not authenticated
- sendError(getString("login-error"));
+ SyncopeEnduserSession.get().error(getString("login-error"));
notificationPanel.refresh(target);
}
}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/MustChangePassword.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/MustChangePassword.java
index 0480618..4649c41 100644
--- a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/MustChangePassword.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/MustChangePassword.java
@@ -19,48 +19,57 @@
package org.apache.syncope.client.enduser.pages;
import org.apache.syncope.client.enduser.SyncopeEnduserSession;
-import org.apache.syncope.client.enduser.rest.UserSelfRestClient;
+import org.apache.syncope.client.enduser.commons.EnduserConstants;
import org.apache.syncope.client.ui.commons.Constants;
-import org.apache.syncope.client.ui.commons.pages.AbstractMustChangePassword;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxPasswordFieldPanel;
+import org.apache.syncope.client.enduser.rest.UserSelfRestClient;
import org.apache.syncope.common.lib.to.UserTO;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.request.mapper.parameter.PageParameters;
-public class MustChangePassword extends AbstractMustChangePassword {
+public class MustChangePassword extends AbstractChangePassword {
private static final long serialVersionUID = 8581970794722709800L;
public MustChangePassword(final PageParameters parameters) {
super(parameters);
+
+ setDomain(parameters);
+ disableSidebar();
}
@Override
- protected void doSubmit(final AjaxRequestTarget target) {
+ protected void doPwdSubmit(final AjaxRequestTarget target, final AjaxPasswordFieldPanel passwordField) {
+ PageParameters parameters = new PageParameters();
try {
UserSelfRestClient.changePassword(passwordField.getModelObject());
SyncopeEnduserSession.get().invalidate();
-
- final PageParameters parameters = new PageParameters();
+ parameters.add(EnduserConstants.STATUS, Constants.OPERATION_SUCCEEDED);
+ parameters.add(Constants.NOTIFICATION_TITLE_PARAM, getString("self.pwd.change.success"));
parameters.add(Constants.NOTIFICATION_MSG_PARAM, getString("self.pwd.change.success"));
- setResponsePage(getApplication().getHomePage(), parameters);
-
- setResponsePage(getApplication().getHomePage(), parameters);
+ SyncopeEnduserSession.get().success(getString(Constants.OPERATION_SUCCEEDED));
} catch (Exception e) {
LOG.error("While changing password for {}",
SyncopeEnduserSession.get().getSelfTO().getUsername(), e);
+ parameters.add(EnduserConstants.STATUS, Constants.OPERATION_ERROR);
+ parameters.add(Constants.NOTIFICATION_TITLE_PARAM, getString("self.pwd.change.error"));
+ parameters.add(Constants.NOTIFICATION_MSG_PARAM, getString("self.pwd.change.error.msg"));
SyncopeEnduserSession.get().onException(e);
- notificationPanel.refresh(target);
}
+ notificationPanel.refresh(target);
+ setResponsePage(SelfResult.class, parameters);
}
@Override
- protected UserTO getLoggedUser() {
+ protected UserTO getPwdLoggedUser() {
return SyncopeEnduserSession.get().getSelfTO();
}
@Override
- protected void doCancel() {
- setResponsePage(getApplication().getHomePage());
+ protected void doPwdCancel() {
+ SyncopeEnduserSession.get().invalidate();
+ final PageParameters parameters = new PageParameters();
+ setResponsePage(getApplication().getHomePage(), parameters);
}
}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/Self.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/Self.java
deleted file mode 100644
index aab4197..0000000
--- a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/Self.java
+++ /dev/null
@@ -1,137 +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.enduser.pages;
-
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.syncope.client.enduser.SyncopeEnduserSession;
-import org.apache.syncope.client.enduser.layout.AnyLayoutUtils;
-import org.apache.syncope.client.enduser.layout.UserFormLayoutInfo;
-import org.apache.syncope.client.ui.commons.Constants;
-import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
-import org.apache.syncope.client.ui.commons.wizards.AjaxWizardBuilder;
-import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
-import org.apache.syncope.client.ui.commons.wizards.any.UserWrapper;
-import org.apache.syncope.common.keymaster.client.api.ConfParamOps;
-import org.apache.syncope.common.lib.SyncopeConstants;
-import org.apache.syncope.common.lib.to.UserTO;
-import org.apache.syncope.common.rest.api.service.SyncopeService;
-import org.apache.wicket.event.IEvent;
-import org.apache.wicket.event.IEventSource;
-import org.apache.wicket.markup.html.WebPage;
-import org.apache.wicket.request.mapper.parameter.PageParameters;
-import org.apache.wicket.spring.injection.annot.SpringBean;
-
-public class Self extends BaseEnduserWebPage implements IEventSource {
-
- private static final long serialVersionUID = 164651008547631054L;
-
- public static final String NEW_USER_PARAM = "newUser";
-
- private static final ObjectMapper MAPPER = new ObjectMapper();
-
- @SpringBean
- private ConfParamOps confParamOps;
-
- private AjaxWizardBuilder<AnyWrapper<UserTO>> wizardBuilder;
-
- protected static final String WIZARD_ID = "wizard";
-
- public Self(final PageParameters parameters) {
- super(parameters);
-
- body.add(buildWizard(SyncopeEnduserSession.get().isAuthenticated()
- ? SyncopeEnduserSession.get().getSelfTO()
- : buildNewUserTO(parameters),
- SyncopeEnduserSession.get().isAuthenticated()
- ? AjaxWizard.Mode.EDIT
- : AjaxWizard.Mode.CREATE));
- }
-
- @Override
- @SuppressWarnings("unchecked")
- public void onEvent(final IEvent<?> event) {
- if (event.getPayload() instanceof AjaxWizard.NewItemEvent) {
- if (event.getPayload() instanceof AjaxWizard.NewItemCancelEvent) {
- @SuppressWarnings("unchecked")
- final Class<? extends WebPage> beforeLogout = (Class<? extends WebPage>) SyncopeEnduserSession.get().
- getAttribute(Constants.BEFORE_LOGOUT_PAGE);
- if (beforeLogout == null) {
- SyncopeEnduserSession.get().invalidate();
- setResponsePage(getApplication().getHomePage());
- } else {
- setResponsePage(beforeLogout);
- }
- } else if (event.getPayload() instanceof AjaxWizard.NewItemFinishEvent) {
- SyncopeEnduserSession.get().invalidate();
-
- final PageParameters parameters = new PageParameters();
- parameters.add(Constants.NOTIFICATION_MSG_PARAM, getString("self.wizard.success"));
- setResponsePage(getApplication().getHomePage(), parameters);
- }
- }
- super.onEvent(event);
- }
-
- @Override
- protected void onBeforeRender() {
- super.onBeforeRender();
- navbar.setActiveNavItem(getClass().getSimpleName().toLowerCase());
- }
-
- protected final AjaxWizard<AnyWrapper<UserTO>> buildWizard(final UserTO userTO, final AjaxWizard.Mode mode) {
- String formLayoutConfParam = confParamOps.get(
- SyncopeEnduserSession.get().getDomain(),
- Constants.ENDUSER_ANYLAYOUT,
- AnyLayoutUtils.getDefaultValue(),
- String.class);
-
- UserFormLayoutInfo formLayoutInfo =
- StringUtils.isBlank(formLayoutConfParam)
- ? new UserFormLayoutInfo()
- : AnyLayoutUtils.fromJsonString(formLayoutConfParam);
-
- wizardBuilder = (AjaxWizardBuilder<AnyWrapper<UserTO>>) AnyLayoutUtils.newUserWizardBuilder(
- userTO,
- SyncopeEnduserSession.get().getService(SyncopeService.class).platform().getUserClasses(),
- formLayoutInfo,
- this.getPageReference());
- wizardBuilder.setItem(new UserWrapper(userTO));
- return wizardBuilder.build(WIZARD_ID, mode);
- }
-
- private static UserTO buildNewUserTO(final PageParameters parameters) {
- UserTO userTO = null;
- if (parameters != null) {
- if (!parameters.get(NEW_USER_PARAM).isNull()) {
- try {
- userTO = MAPPER.readValue(parameters.get(NEW_USER_PARAM).toString(), UserTO.class);
- } catch (JsonProcessingException e) {
- LOG.error("While reading user data from social registration", e);
- }
- }
- }
- if (userTO == null) {
- userTO = new UserTO();
- }
- userTO.setRealm(SyncopeConstants.ROOT_REALM);
- return userTO;
- }
-}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/SelfConfirmPasswordReset.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/SelfConfirmPasswordReset.java
index f937507..6038d73 100644
--- a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/SelfConfirmPasswordReset.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/SelfConfirmPasswordReset.java
@@ -18,127 +18,95 @@
*/
package org.apache.syncope.client.enduser.pages;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.stream.Collectors;
+import de.agilecoders.wicket.extensions.markup.html.bootstrap.form.password.strength.PasswordStrengthBehavior;
+import de.agilecoders.wicket.extensions.markup.html.bootstrap.form.password.strength.PasswordStrengthConfig;
import org.apache.syncope.client.enduser.SyncopeEnduserSession;
+import org.apache.syncope.client.enduser.commons.EnduserConstants;
import org.apache.syncope.client.ui.commons.Constants;
-import org.apache.syncope.client.ui.commons.DomainDropDown;
-import org.apache.syncope.client.ui.commons.markup.html.form.AjaxPasswordFieldPanel;
-import org.apache.syncope.client.ui.commons.markup.html.form.FieldPanel;
-import org.apache.syncope.common.keymaster.client.api.DomainOps;
-import org.apache.syncope.common.keymaster.client.api.model.Domain;
+import org.apache.syncope.client.ui.commons.panels.CardPanel;
+import org.apache.syncope.client.ui.commons.wizards.any.PasswordPanel;
+import org.apache.syncope.client.ui.commons.wizards.any.UserWrapper;
import org.apache.syncope.common.lib.SyncopeClientException;
-import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.lib.to.UserTO;
import org.apache.syncope.common.rest.api.service.UserSelfService;
import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
import org.apache.wicket.ajax.markup.html.form.AjaxButton;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.form.Button;
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.validation.EqualPasswordInputValidator;
-import org.apache.wicket.model.LoadableDetachableModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.request.mapper.parameter.PageParameters;
-import org.apache.wicket.spring.injection.annot.SpringBean;
-public class SelfConfirmPasswordReset extends BaseEnduserWebPage {
+public class SelfConfirmPasswordReset extends BasePage {
private static final long serialVersionUID = -2166782304542750726L;
- @SpringBean
- private DomainOps domainOps;
-
- private final LoadableDetachableModel<List<String>> domains = new LoadableDetachableModel<List<String>>() {
-
- private static final long serialVersionUID = 4659376149825914247L;
-
- @Override
- protected List<String> load() {
- List<String> current = new ArrayList<>();
- current.addAll(domainOps.list().stream().map(Domain::getKey).sorted().collect(Collectors.toList()));
- current.add(0, SyncopeConstants.MASTER_DOMAIN);
- return current;
- }
- };
+ private static final String CONFIRM_PASSWORD_RESET = "confirmPasswordReset";
public SelfConfirmPasswordReset(final PageParameters parameters) {
- super(parameters);
+ super(parameters, CONFIRM_PASSWORD_RESET);
- if (parameters.get("token").isEmpty()) {
- LOG.debug("No token parameter found in the request url");
- parameters.add("errorMessage", getString("self.confirm.pwd.reset.error.empty"));
- setResponsePage(getApplication().getHomePage(), parameters);
+ setDomain(parameters);
+ disableSidebar();
+
+ if (parameters == null || parameters.get("token").isEmpty()) {
+ LOG.error("No token parameter found in the request url");
+
+ PageParameters homeParameters = new PageParameters();
+ homeParameters.add("errorMessage", getString("self.confirm.pwd.reset.error.empty"));
+ setResponsePage(getApplication().getHomePage(), homeParameters);
}
- navbar.setEnabled(false);
- navbar.setVisible(false);
-
WebMarkupContainer content = new WebMarkupContainer("content");
content.setOutputMarkupId(true);
- body.add(content);
+ contentWrapper.add(content);
Form<?> form = new StatelessForm<>("selfConfirmPwdResetForm");
form.setOutputMarkupId(true);
content.add(form);
- DomainDropDown domainSelect = new DomainDropDown("domain", domains);
- domainSelect.add(new AjaxFormComponentUpdatingBehavior(Constants.ON_BLUR) {
+ UserTO fakeUserTO = new UserTO();
+ PasswordPanel passwordPanel = new PasswordPanel(
+ EnduserConstants.CONTENT_PANEL,
+ new UserWrapper(fakeUserTO),
+ false,
+ false,
+ new PasswordStrengthBehavior(new PasswordStrengthConfig().
+ withDebug(false).
+ withShowVerdictsInsideProgressBar(true).
+ withShowProgressBar(true)));
+ passwordPanel.setOutputMarkupId(true);
- private static final long serialVersionUID = -1107858522700306810L;
+ form.add(new CardPanel.Builder<PasswordPanel>()
+ .setName("selfConfirmPasswordResetPanel")
+ .setComponent(passwordPanel)
+ .isVisible(true)
+ .build("selfConfirmPasswordResetPanelCard"));
- @Override
- protected void onUpdate(final AjaxRequestTarget target) {
- // nothing to do
- }
- }).add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
-
- private static final long serialVersionUID = -1107858522700306810L;
-
- @Override
- protected void onUpdate(final AjaxRequestTarget target) {
- // nothing to do
- }
- });
- form.add(domainSelect);
-
- AjaxPasswordFieldPanel passwordField = new AjaxPasswordFieldPanel(
- "password", getString("password"), new Model<>());
- passwordField.setRequired(true);
- passwordField.setMarkupId("password");
- passwordField.setPlaceholder(getString("password"));
- ((PasswordTextField) passwordField.getField()).setResetPassword(false);
- form.add(passwordField);
-
- FieldPanel<String> confirmPasswordField = new AjaxPasswordFieldPanel(
- "confirmPassword", getString("confirm-password"), new Model<>());
- confirmPasswordField.setRequired(true);
- confirmPasswordField.setMarkupId("confirmPassword");
- confirmPasswordField.setPlaceholder(getString("confirm-password"));
- ((PasswordTextField) confirmPasswordField.getField()).setResetPassword(false);
- form.add(confirmPasswordField);
-
- form.add(new EqualPasswordInputValidator(passwordField.getField(), confirmPasswordField.getField()));
-
- AjaxButton submitButton = new AjaxButton("submit", new Model<>(getString("submit"))) {
+ AjaxButton submit = new AjaxButton("submit", new Model<>(getString("submit"))) {
private static final long serialVersionUID = 509325877101838812L;
@Override
protected void onSubmit(final AjaxRequestTarget target) {
+ PageParameters params = new PageParameters();
try {
SyncopeEnduserSession.get().getService(UserSelfService.class).confirmPasswordReset(
- parameters.get("token").toString(), passwordField.getDefaultModelObjectAsString());
- PageParameters parameters = new PageParameters();
- parameters.add(Constants.NOTIFICATION_MSG_PARAM, getString("self.confirm.pwd.reset.success"));
- setResponsePage(getApplication().getHomePage(), parameters);
+ parameters.get("token").toString(), fakeUserTO.getPassword());
+ params.add(EnduserConstants.STATUS, Constants.OPERATION_SUCCEEDED);
+ params.add(Constants.NOTIFICATION_TITLE_PARAM, getString("self.confirm.pwd.reset.success"));
+ params.add(Constants.NOTIFICATION_MSG_PARAM, getString("self.confirm.pwd.reset.success.msg"));
+ SyncopeEnduserSession.get().success(getString(Constants.OPERATION_SUCCEEDED));
+ parameters.add(EnduserConstants.LANDING_PAGE, Login.class.getName());
+ setResponsePage(SelfResult.class, params);
} catch (SyncopeClientException sce) {
LOG.error("Unable to complete the 'Password Reset Confirmation' process", sce);
+ params.add(EnduserConstants.STATUS, Constants.OPERATION_ERROR);
+ params.add(Constants.NOTIFICATION_TITLE_PARAM, getString("self.confirm.pwd.reset.error"));
+ params.add(Constants.NOTIFICATION_MSG_PARAM, getString("self.confirm.pwd.reset.error.msg"));
SyncopeEnduserSession.get().onException(sce);
- ((BaseEnduserWebPage) getPageReference().getPage()).getNotificationPanel().refresh(target);
+ ((BasePage) getPageReference().getPage()).getNotificationPanel().refresh(target);
}
}
@@ -147,8 +115,8 @@
notificationPanel.refresh(target);
}
};
- form.setDefaultButton(submitButton);
- form.add(submitButton);
+ form.setDefaultButton(submit);
+ form.add(submit);
Button cancel = new Button("cancel") {
@@ -158,7 +126,6 @@
public void onSubmit() {
setResponsePage(getApplication().getHomePage());
}
-
};
cancel.setOutputMarkupId(true);
cancel.setDefaultFormProcessing(false);
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/SelfPasswordReset.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/SelfPasswordReset.java
index 0d53e99..3d34ed0 100644
--- a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/SelfPasswordReset.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/SelfPasswordReset.java
@@ -18,33 +18,219 @@
*/
package org.apache.syncope.client.enduser.pages;
-import org.apache.syncope.client.enduser.panels.SelfPwdResetPanel;
+import org.apache.syncope.client.enduser.SyncopeWebApplication;
+import org.apache.syncope.client.enduser.SyncopeEnduserSession;
+import org.apache.syncope.client.enduser.commons.EnduserConstants;
+import org.apache.syncope.client.enduser.panels.captcha.CaptchaPanel;
+import org.apache.syncope.client.enduser.rest.UserSelfRestClient;
+import org.apache.syncope.client.ui.commons.Constants;
+import org.apache.syncope.client.ui.commons.panels.CardPanel;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.SecurityQuestionTO;
+import org.apache.syncope.common.rest.api.service.SecurityQuestionService;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
+import org.apache.wicket.ajax.markup.html.AjaxLink;
+import org.apache.wicket.ajax.markup.html.form.AjaxButton;
import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.form.Button;
import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.markup.html.form.TextField;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.model.PropertyModel;
+import org.apache.wicket.model.ResourceModel;
import org.apache.wicket.request.mapper.parameter.PageParameters;
-public class SelfPasswordReset extends BaseEnduserWebPage {
+public class SelfPasswordReset extends BasePage {
private static final long serialVersionUID = 164651008547631054L;
+ private static final String SELF_PWD_RESET = "page.selfPwdReset";
+
+ private String usernameValue;
+
+ private String securityAnswerValue;
+
+ private final CaptchaPanel<Void> captcha;
+
private final SelfPwdResetPanel pwdResetPanel;
public SelfPasswordReset(final PageParameters parameters) {
- super(parameters);
+ super(parameters, SELF_PWD_RESET);
- navbar.setEnabled(false);
- navbar.setVisible(false);
+ setDomain(parameters);
+ disableSidebar();
+
+ captcha = new CaptchaPanel<>("captchaPanel");
+ captcha.setOutputMarkupPlaceholderTag(true);
+ captcha.setVisible(SyncopeWebApplication.get().isCaptchaEnabled());
WebMarkupContainer content = new WebMarkupContainer("content");
content.setOutputMarkupId(true);
- body.add(content);
+ contentWrapper.add(content);
Form<?> form = new Form<>("selfPwdResetForm");
content.add(form);
- pwdResetPanel = new SelfPwdResetPanel("selfPwdResetPanel", getPageReference());
+ pwdResetPanel = new SelfPwdResetPanel(EnduserConstants.CONTENT_PANEL, captcha, getPageReference());
pwdResetPanel.setOutputMarkupId(true);
- form.add(pwdResetPanel);
+ form.add(new CardPanel.Builder<SelfPwdResetPanel>()
+ .setName("selfPasswordResetPanel")
+ .setComponent(pwdResetPanel)
+ .isVisible(true)
+ .build("selfPasswordResetPanelCard"));
+
+ AjaxButton submitButton = new AjaxButton("submit") {
+
+ private static final long serialVersionUID = 4284361595033427185L;
+
+ @Override
+ protected void onSubmit(final AjaxRequestTarget target) {
+ boolean checked = true;
+ if (SyncopeWebApplication.get().isCaptchaEnabled()) {
+ checked = captcha.check();
+ }
+ if (!checked) {
+ SyncopeEnduserSession.get().error(getString(Constants.CAPTCHA_ERROR));
+ SelfPasswordReset.this.getNotificationPanel().refresh(target);
+ } else {
+ PageParameters parameters = new PageParameters();
+ try {
+ UserSelfRestClient.requestPasswordReset(usernameValue, securityAnswerValue);
+ parameters.add(EnduserConstants.STATUS, Constants.OPERATION_SUCCEEDED);
+ parameters.add(Constants.NOTIFICATION_TITLE_PARAM, getString("self.pwd.reset.success"));
+ parameters.add(Constants.NOTIFICATION_MSG_PARAM, getString("self.pwd.reset.success.msg"));
+ parameters.add(EnduserConstants.LANDING_PAGE, Login.class.getName());
+ setResponsePage(SelfResult.class, parameters);
+ } catch (SyncopeClientException sce) {
+ LOG.error("Unable to reset password of [{}]", usernameValue, sce);
+ SyncopeEnduserSession.get().onException(sce);
+ SelfPasswordReset.this.getNotificationPanel().refresh(target);
+ }
+ }
+ }
+
+ };
+ submitButton.setOutputMarkupId(true);
+ submitButton.setDefaultFormProcessing(false);
+ form.add(submitButton);
+
+ Button cancel = new Button("cancel") {
+
+ private static final long serialVersionUID = 3669569969172391336L;
+
+ @Override
+ public void onSubmit() {
+ setResponsePage(getApplication().getHomePage());
+ }
+
+ };
+ cancel.setOutputMarkupId(true);
+ cancel.setDefaultFormProcessing(false);
+ form.add(cancel);
+ }
+
+ public class SelfPwdResetPanel extends Panel {
+
+ private static final long serialVersionUID = -2841210052053545578L;
+
+ private final TextField<String> securityQuestion;
+
+ SelfPwdResetPanel(final String id, final CaptchaPanel<Void> captcha, final PageReference pageRef) {
+ super(id);
+
+ boolean isSecurityQuestionEnabled =
+ SyncopeEnduserSession.get().getPlatformInfo().isPwdResetRequiringSecurityQuestions();
+
+ TextField<String> username = new TextField<>("username",
+ new PropertyModel<>(SelfPasswordReset.this, "usernameValue"), String.class);
+ username.add(new AjaxFormComponentUpdatingBehavior(Constants.ON_BLUR) {
+
+ private static final long serialVersionUID = -1107858522700306810L;
+
+ @Override
+ protected void onUpdate(final AjaxRequestTarget target) {
+ if (isSecurityQuestionEnabled) {
+ loadSecurityQuestion(pageRef, target);
+ }
+ }
+ });
+ username.setRequired(true);
+ add(username);
+
+ Label sqLabel =
+ new Label("securityQuestionLabel", new ResourceModel("securityQuestion", "securityQuestion"));
+ sqLabel.setOutputMarkupPlaceholderTag(true);
+ sqLabel.setVisible(isSecurityQuestionEnabled);
+ add(sqLabel);
+
+ securityQuestion =
+ new TextField<>("securityQuestion", new PropertyModel<>(Model.of(), "content"), String.class);
+ securityQuestion.setOutputMarkupId(true);
+ securityQuestion.setEnabled(false);
+ securityQuestion.setOutputMarkupPlaceholderTag(true);
+ securityQuestion.setVisible(isSecurityQuestionEnabled);
+ add(securityQuestion);
+
+ Label notLoading = new Label("not.loading", new ResourceModel("not.loading", "not.loading"));
+ notLoading.setOutputMarkupPlaceholderTag(true);
+ notLoading.setVisible(isSecurityQuestionEnabled);
+ add(notLoading);
+
+ AjaxLink<Void> reloadLink = new AjaxLink<Void>("reloadLink") {
+
+ private static final long serialVersionUID = -817438685948164787L;
+
+ @Override
+ public void onClick(final AjaxRequestTarget target) {
+ loadSecurityQuestion(pageRef, target);
+ }
+ };
+ reloadLink.setOutputMarkupPlaceholderTag(true);
+ reloadLink.setVisible(isSecurityQuestionEnabled);
+ add(reloadLink);
+
+ Label saLabel = new Label("securityAnswerLabel", new ResourceModel("securityAnswer", "securityAnswer"));
+ saLabel.setOutputMarkupPlaceholderTag(true);
+ saLabel.setVisible(isSecurityQuestionEnabled);
+ add(saLabel);
+
+ TextField<String> securityAnswer =
+ new TextField<>("securityAnswer", new PropertyModel<>(SelfPasswordReset.this,
+ "securityAnswerValue"), String.class);
+ securityAnswer.add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
+
+ private static final long serialVersionUID = -1107858522700306810L;
+
+ @Override
+ protected void onUpdate(final AjaxRequestTarget target) {
+ // do nothing
+ }
+ });
+ securityAnswer.setRequired(isSecurityQuestionEnabled);
+ securityAnswer.setOutputMarkupPlaceholderTag(true);
+ securityAnswer.setVisible(isSecurityQuestionEnabled);
+ add(securityAnswer);
+
+ add(captcha);
+ }
+
+ protected void loadSecurityQuestion(final PageReference pageRef, final AjaxRequestTarget target) {
+ try {
+ SecurityQuestionTO securityQuestionTO = SyncopeEnduserSession.get().getService(
+ SecurityQuestionService.class).readByUser(usernameValue);
+ // set security question field model
+ securityQuestion.setModel(Model.of(securityQuestionTO.getContent()));
+ target.add(securityQuestion);
+ } catch (Exception e) {
+ LOG.error("Unable to get security question for [{}]", usernameValue, e);
+ SyncopeEnduserSession.get().onException(e);
+ ((BasePage) pageRef.getPage()).getNotificationPanel().refresh(target);
+ }
+ }
}
}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/SelfRegistration.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/SelfRegistration.java
new file mode 100644
index 0000000..ec85d59
--- /dev/null
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/SelfRegistration.java
@@ -0,0 +1,86 @@
+/*
+ * 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.enduser.pages;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.syncope.client.enduser.SyncopeWebApplication;
+import org.apache.syncope.client.enduser.SyncopeEnduserSession;
+import org.apache.syncope.client.enduser.layout.UserFormLayoutInfo;
+import org.apache.syncope.client.enduser.panels.UserSelfFormPanel;
+import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.common.rest.api.service.SyncopeService;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
+
+public class SelfRegistration extends BasePage {
+
+ private static final long serialVersionUID = -1100228004207271270L;
+
+ private static final String SELF_REGISTRATION = "page.selfRegistration";
+
+ public static final String NEW_USER_PARAM = "newUser";
+
+ private static final ObjectMapper MAPPER = new ObjectMapper();
+
+ public SelfRegistration(final PageParameters parameters) {
+ super(parameters, SELF_REGISTRATION);
+
+ setDomain(parameters);
+ disableSidebar();
+
+ WebMarkupContainer content = new WebMarkupContainer("content");
+ content.setOutputMarkupId(true);
+ contentWrapper.add(content);
+
+ UserSelfFormPanel selfRegistrationPanel = new UserSelfFormPanel(
+ "selfRegistrationPanel",
+ buildNewUserTO(parameters),
+ buildNewUserTO(parameters),
+ SyncopeEnduserSession.get().getService(SyncopeService.class).platform().getUserClasses(),
+ buildFormLayout(),
+ getPageReference());
+ selfRegistrationPanel.setOutputMarkupId(true);
+ content.add(selfRegistrationPanel);
+ }
+
+ private UserFormLayoutInfo buildFormLayout() {
+ UserFormLayoutInfo customlayoutInfo = SyncopeWebApplication.get().getCustomFormLayout();
+ return customlayoutInfo != null ? customlayoutInfo : new UserFormLayoutInfo();
+ }
+
+ private static UserTO buildNewUserTO(final PageParameters parameters) {
+ UserTO userTO = null;
+ if (parameters != null) {
+ if (!parameters.get(NEW_USER_PARAM).isNull()) {
+ try {
+ userTO = MAPPER.readValue(parameters.get(NEW_USER_PARAM).toString(), UserTO.class);
+ } catch (JsonProcessingException e) {
+ LOG.error("While reading user data from social registration", e);
+ }
+ }
+ }
+ if (userTO == null) {
+ userTO = new UserTO();
+ }
+ userTO.setRealm(SyncopeConstants.ROOT_REALM);
+ return userTO;
+ }
+}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/SelfResult.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/SelfResult.java
new file mode 100644
index 0000000..4d415c4
--- /dev/null
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/SelfResult.java
@@ -0,0 +1,67 @@
+/*
+ * 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.enduser.pages;
+
+import org.apache.syncope.client.enduser.BookmarkablePageLinkBuilder;
+import org.apache.syncope.client.enduser.commons.EnduserConstants;
+import org.apache.syncope.client.ui.commons.Constants;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.WebPage;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.link.BookmarkablePageLink;
+import org.apache.wicket.markup.html.panel.Fragment;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
+
+public class SelfResult extends BasePage {
+
+ private static final long serialVersionUID = 3804053409052140145L;
+
+ private static final String RESULT_PAGE = "page.resultPage";
+
+ @SuppressWarnings("unchecked")
+ public SelfResult(final PageParameters parameters) {
+ super(parameters, RESULT_PAGE);
+
+ WebMarkupContainer content = new WebMarkupContainer("content");
+ content.setOutputMarkupId(true);
+ contentWrapper.add(content);
+ Class<? extends WebPage> page;
+ try {
+ page = (Class<? extends WebPage>) Class.forName(parameters.get(EnduserConstants.LANDING_PAGE).
+ toString("org.apache.syncope.client.enduser.pages.Login"));
+ } catch (ClassNotFoundException e) {
+ LOG.debug("Login page not found", e);
+ page = Login.class;
+ }
+ if (page.equals(Login.class)) {
+ BookmarkablePageLink<WebPage> login =
+ new BookmarkablePageLink<>("login", Login.class);
+ content.add(login.setOutputMarkupId(true));
+ disableSidebar();
+ } else {
+ content.add(BookmarkablePageLinkBuilder.build("login", page));
+ }
+
+ content.add(new Label("resultTitle", parameters.get(Constants.NOTIFICATION_TITLE_PARAM).toString()));
+ content.add(new Label("resultMessage", parameters.get(Constants.NOTIFICATION_MSG_PARAM).toString()));
+ content.add(new Fragment("statusIcon",
+ Constants.OPERATION_SUCCEEDED.equals(parameters.get(EnduserConstants.STATUS).toString())
+ ? "successIcon" : "errorIcon", content));
+ }
+}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/AbstractAnyFormPanel.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/AbstractAnyFormPanel.java
new file mode 100644
index 0000000..18c461a
--- /dev/null
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/AbstractAnyFormPanel.java
@@ -0,0 +1,95 @@
+/*
+ * 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.enduser.panels;
+
+import java.io.Serializable;
+import org.apache.syncope.client.enduser.pages.BasePage;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.markup.html.form.AjaxButton;
+import org.apache.wicket.markup.html.form.Button;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.model.CompoundPropertyModel;
+
+public abstract class AbstractAnyFormPanel<T extends Serializable> extends AbstractFormPanel<T> {
+
+ private static final long serialVersionUID = -5976166731584959275L;
+
+ protected final Form<T> form;
+
+ public AbstractAnyFormPanel(final String id, final T defaultItem, final PageReference pageReference) {
+ super(id, defaultItem, pageReference);
+
+ form = new Form<>("form");
+ form.setOutputMarkupId(true);
+ add(form);
+ AjaxButton submitButton = new AjaxButton("submit") {
+
+ private static final long serialVersionUID = 4284361595033427185L;
+
+ @Override
+ protected void onSubmit(final AjaxRequestTarget target) {
+ onFormSubmit(target);
+ }
+
+ @Override
+ protected void onError(final AjaxRequestTarget target) {
+ ((BasePage) getPage()).getNotificationPanel().refresh(target);
+ }
+ };
+
+ submitButton.setOutputMarkupId(true);
+ submitButton.setDefaultFormProcessing(true);
+ form.add(submitButton);
+
+ Button cancel = new Button("cancel") {
+
+ private static final long serialVersionUID = 3669569969172391336L;
+
+ @Override
+ public void onSubmit() {
+ setResponsePage(getApplication().getHomePage());
+ }
+
+ };
+ cancel.setOutputMarkupId(true);
+ cancel.setDefaultFormProcessing(false);
+ form.add(cancel);
+ }
+
+ public Form<T> getForm() {
+ return form;
+ }
+
+ public void setFormModel(final T modelObject) {
+ form.setModel(new CompoundPropertyModel<>(modelObject));
+ }
+
+ protected void onCancelInternal(final T modelObject) {
+ }
+
+ protected Serializable onApplyInternal(final T modelObject) {
+ // do nothing
+ return null;
+ }
+
+ protected abstract void buildLayout(T modelObject);
+
+ protected abstract void onFormSubmit(AjaxRequestTarget target);
+}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/AbstractFormPanel.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/AbstractFormPanel.java
new file mode 100644
index 0000000..312ea27
--- /dev/null
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/AbstractFormPanel.java
@@ -0,0 +1,63 @@
+/*
+ * 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.enduser.panels;
+
+import java.io.Serializable;
+import org.apache.commons.lang3.SerializationUtils;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public abstract class AbstractFormPanel<T extends Serializable> extends Panel {
+
+ private static final long serialVersionUID = 6650311507433421554L;
+
+ protected static final Logger LOG = LoggerFactory.getLogger(AbstractFormPanel.class);
+
+ protected final PageReference pageRef;
+
+ protected final T defaultItem;
+
+ protected T item;
+
+ public AbstractFormPanel(final String id, final T defaultItem, final PageReference pageReference) {
+ super(id);
+ this.defaultItem = defaultItem;
+ this.pageRef = pageReference;
+ }
+
+ protected T getOriginalItem() {
+ return item;
+ }
+
+ protected T newModelObject() {
+ if (item == null) {
+ // keep the original item: the which one before the changes performed during wizard browsing
+ item = SerializationUtils.clone(defaultItem);
+ }
+
+ // instantiate a new model object and return it
+ return SerializationUtils.clone(item);
+ }
+
+ public PageReference getPageReference() {
+ return pageRef;
+ }
+}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/AnyFormPanel.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/AnyFormPanel.java
new file mode 100644
index 0000000..ed9e79b
--- /dev/null
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/AnyFormPanel.java
@@ -0,0 +1,184 @@
+/*
+ * 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.enduser.panels;
+
+import org.apache.syncope.client.enduser.SyncopeWebApplication;
+import org.apache.syncope.client.enduser.layout.UserFormLayoutInfo;
+import org.apache.syncope.client.enduser.panels.captcha.CaptchaPanel;
+import org.apache.syncope.client.ui.commons.panels.CardPanel;
+import org.apache.syncope.client.ui.commons.wizards.any.UserWrapper;
+import org.apache.syncope.common.lib.Attr;
+import org.apache.syncope.common.lib.to.AnyTO;
+import org.apache.syncope.common.lib.to.GroupableRelatableTO;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.wicket.PageReference;
+import java.util.List;
+import org.apache.syncope.client.enduser.commons.EnduserConstants;
+import org.apache.syncope.client.enduser.panels.any.DerAttrs;
+import org.apache.syncope.client.enduser.panels.any.Details;
+import org.apache.syncope.client.enduser.panels.any.Groups;
+import org.apache.syncope.client.enduser.panels.any.PlainAttrs;
+import org.apache.syncope.client.enduser.panels.any.Resources;
+import org.apache.syncope.client.enduser.panels.any.VirAttrs;
+
+public abstract class AnyFormPanel extends AbstractAnyFormPanel<UserWrapper> {
+
+ private static final long serialVersionUID = -2720486919461006370L;
+
+ protected final List<String> anyTypeClasses;
+
+ protected CaptchaPanel<Void> captcha;
+
+ protected UserFormLayoutInfo formLayoutInfo;
+
+ public AnyFormPanel(final String id,
+ final UserTO anyTO,
+ final List<String> anyTypeClasses,
+ final UserFormLayoutInfo formLayoutInfo,
+ final PageReference pageReference) {
+
+ super(id, new UserWrapper(anyTO), pageReference);
+
+ this.formLayoutInfo = formLayoutInfo;
+ this.anyTypeClasses = anyTypeClasses;
+ }
+
+ @SuppressWarnings("unchecked")
+ public AnyFormPanel(final String id,
+ final UserWrapper wrapper,
+ final List<String> anyTypeClasses,
+ final UserFormLayoutInfo formLayoutInfo,
+ final PageReference pageReference) {
+
+ super(id, wrapper, pageReference);
+
+ this.formLayoutInfo = formLayoutInfo;
+ this.anyTypeClasses = anyTypeClasses;
+ }
+
+ protected Details<UserTO> addOptionalDetailsPanel(final UserWrapper modelObject) {
+ Details<UserTO> details = new Details<>(EnduserConstants.CONTENT_PANEL, modelObject, false, true, pageRef);
+ details.setOutputMarkupId(true);
+ return details;
+ }
+
+ @Override
+ protected void buildLayout(final UserWrapper modelObject) {
+ form.add(new CardPanel.Builder<>()
+ .setName("details")
+ .setComponent(addOptionalDetailsPanel(modelObject))
+ .isVisible(formLayoutInfo.isDetailsManagement()).build("userDetailsPanelCard"));
+
+ Groups groups = new Groups(EnduserConstants.CONTENT_PANEL, modelObject, false);
+ setOutputMarkupId(true);
+
+ form.add(new CardPanel.Builder<Groups>()
+ .setName("groups")
+ .setComponent(groups)
+ .isVisible(formLayoutInfo.isGroups()).build("groupsPanelCard"));
+
+ PlainAttrs plainAttrs = new PlainAttrs(EnduserConstants.CONTENT_PANEL,
+ modelObject, anyTypeClasses, formLayoutInfo.getWhichPlainAttrs());
+ plainAttrs.setOutputMarkupId(true);
+
+ form.add(new CardPanel.Builder<PlainAttrs>()
+ .setName("attributes.plain")
+ .setComponent(plainAttrs)
+ .isVisible(formLayoutInfo.isPlainAttrs() && plainAttrs.isPanelVisible()).build("plainAttrsPanelCard"));
+
+ DerAttrs derAttrs = new DerAttrs(EnduserConstants.CONTENT_PANEL,
+ modelObject, anyTypeClasses, formLayoutInfo.getWhichDerAttrs());
+ derAttrs.setOutputMarkupId(true);
+
+ form.add(new CardPanel.Builder<DerAttrs>()
+ .setName("attributes.derived")
+ .setComponent(derAttrs)
+ .isVisible(formLayoutInfo.isVirAttrs() && derAttrs.isPanelVisible()).build("derAttrsPanelCard"));
+
+ VirAttrs virAttrs = new VirAttrs(EnduserConstants.CONTENT_PANEL,
+ modelObject, anyTypeClasses, formLayoutInfo.getWhichVirAttrs());
+ virAttrs.setOutputMarkupId(true);
+
+ form.add(new CardPanel.Builder<VirAttrs>()
+ .setName("attributes.virtual")
+ .setComponent(virAttrs)
+ .isVisible(formLayoutInfo.isVirAttrs() && virAttrs.isPanelVisible()).build("virAttrsPanelCard"));
+
+ Resources resources = new Resources(EnduserConstants.CONTENT_PANEL, modelObject);
+ resources.setOutputMarkupId(true);
+
+ form.add(new CardPanel.Builder<Resources>()
+ .setName("resources")
+ .setComponent(resources)
+ .isVisible(formLayoutInfo.isResources()).build("resourcesPanelCard"));
+
+ // add captcha
+ captcha = new CaptchaPanel<>(EnduserConstants.CONTENT_PANEL);
+ captcha.setOutputMarkupPlaceholderTag(true);
+
+ form.add(new CardPanel.Builder<CaptchaPanel<Void>>()
+ .setName("captcha")
+ .setComponent(captcha)
+ .isVisible(SyncopeWebApplication.get().isCaptchaEnabled()).build("captchaPanelCard"));
+ }
+
+ protected void fixPlainAndVirAttrs(final AnyTO updated, final AnyTO original) {
+ // re-add to the updated object any missing plain or virtual attribute (compared to original): this to cope with
+ // form layout, which might have not included some plain or virtual attributes
+ for (Attr plainAttr : original.getPlainAttrs()) {
+ if (!updated.getPlainAttr(plainAttr.getSchema()).isPresent()) {
+ updated.getPlainAttrs().add(plainAttr);
+ }
+ }
+ for (Attr virAttr : original.getVirAttrs()) {
+ if (!updated.getVirAttr(virAttr.getSchema()).isPresent()) {
+ updated.getVirAttrs().add(virAttr);
+ }
+ }
+
+ if (updated instanceof GroupableRelatableTO && original instanceof GroupableRelatableTO) {
+ GroupableRelatableTO.class
+ .cast(original).getMemberships().forEach(oMemb -> {
+ GroupableRelatableTO.class
+ .cast(updated).getMembership(oMemb.getGroupKey()).ifPresent(uMemb -> {
+ oMemb.getPlainAttrs()
+ .stream().
+ filter(attr -> !uMemb.getPlainAttr(attr.getSchema()).isPresent()).
+ forEach(attr -> uMemb.getPlainAttrs().add(attr));
+ oMemb.getVirAttrs()
+ .stream().
+ filter(attr -> !uMemb.getVirAttr(attr.getSchema()).isPresent()).
+ forEach(attr -> uMemb.getVirAttrs().add(attr));
+ }
+ );
+ });
+ }
+
+ // remove from the updated object any plain or virtual attribute without values, thus triggering for removal in
+ // the generated patch
+ updated.getPlainAttrs().removeIf(attr -> attr.getValues().isEmpty());
+ updated.getVirAttrs().removeIf(attr -> attr.getValues().isEmpty());
+ if (updated instanceof GroupableRelatableTO) {
+ GroupableRelatableTO.class.cast(updated).getMemberships().forEach(memb -> {
+ memb.getPlainAttrs().removeIf(attr -> attr.getValues().isEmpty());
+ memb.getVirAttrs().removeIf(attr -> attr.getValues().isEmpty());
+ });
+ }
+ }
+}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/ChangePasswordPanel.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/ChangePasswordPanel.java
new file mode 100644
index 0000000..c5e7fc1
--- /dev/null
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/ChangePasswordPanel.java
@@ -0,0 +1,199 @@
+/*
+ * 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.enduser.panels;
+
+import de.agilecoders.wicket.extensions.markup.html.bootstrap.form.password.strength.PasswordStrengthBehavior;
+import de.agilecoders.wicket.extensions.markup.html.bootstrap.form.password.strength.PasswordStrengthConfig;
+import org.apache.syncope.client.enduser.SyncopeWebApplication;
+import org.apache.syncope.client.enduser.commons.EnduserConstants;
+import org.apache.syncope.client.enduser.panels.captcha.CaptchaPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AbstractFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxPasswordFieldPanel;
+import org.apache.syncope.client.ui.commons.panels.CardPanel;
+import org.apache.syncope.client.ui.commons.panels.NotificationPanel;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.wicket.AttributeModifier;
+import org.apache.wicket.Component;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.markup.html.form.AjaxButton;
+import org.apache.wicket.core.util.string.CssUtils;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.form.Button;
+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.validation.EqualPasswordInputValidator;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.util.string.AppendingStringBuffer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public abstract class ChangePasswordPanel extends Panel {
+
+ protected static final Logger LOG = LoggerFactory.getLogger(ChangePasswordPanel.class);
+
+ private static final long serialVersionUID = -8937593602426944714L;
+
+ protected static final String FORM_SUFFIX = "form_";
+
+ protected StatelessForm<Void> form;
+
+ protected AjaxPasswordFieldPanel passwordField;
+
+ protected AjaxPasswordFieldPanel confirmPasswordField;
+
+ protected CaptchaPanel<Void> captcha;
+
+ public ChangePasswordPanel(final String id, final NotificationPanel notificationPanel) {
+ super(id);
+ form = new StatelessForm<Void>("changePassword") {
+
+ private static final long serialVersionUID = 418292023846536149L;
+
+ @Override
+ protected void appendDefaultButtonField() {
+ AppendingStringBuffer buffer = new AppendingStringBuffer();
+
+ String cssClass = getString(CssUtils.key(Form.class, "hidden-fields"));
+
+ // div that is not visible (but not display:none either)
+ buffer.append(String.format(
+ "<div style=\"width:0px;height:0px;position:absolute;"
+ + "left:-100px;top:-100px;overflow:hidden\" class=\"%s\">",
+ cssClass));
+
+ // add an empty textfield (otherwise IE doesn't work)
+ buffer.append("<input title=\"text_hidden\" "
+ + "aria-label=\"text_hidden\" type=\"text\" "
+ + "tabindex=\"-1\" autocomplete=\"off\"/>");
+
+ // add the submitting component
+ final Component submittingComponent = (Component) getDefaultButton();
+ buffer.append("<input title=\"submit_hidden\" aria-label=\"submit_hidden\" "
+ + "type=\"submit\" tabindex=\"-1\" name=\"");
+ buffer.append(getDefaultButton().getInputName());
+ buffer.append("\" onclick=\" var b=document.getElementById('");
+ buffer.append(submittingComponent.getMarkupId());
+ buffer.append(
+ "'); if (b!=null&&b.onclick!=null&&typeof(b.onclick) != 'undefined') "
+ + "{ var r = Wicket.bind(b.onclick, b)(); if (r != false) b.click(); } "
+ + "else { b.click(); }; return false;\" ");
+ buffer.append(" />");
+
+ // close div
+ buffer.append("</div>");
+
+ getResponse().write(buffer);
+ }
+ };
+ form.setOutputMarkupId(true);
+ add(form);
+
+ passwordField = new AjaxPasswordFieldPanel(
+ "password",
+ getString("password"),
+ new Model<>(),
+ false,
+ new PasswordStrengthBehavior(
+ new PasswordStrengthConfig()
+ .withDebug(true)
+ .withShowVerdictsInsideProgressBar(true)
+ .withShowProgressBar(true)));
+ passwordField.setRequired(true);
+ passwordField.setMarkupId("password");
+ passwordField.setPlaceholder("password");
+
+ Label passwordLabel = (Label) passwordField.get(AbstractFieldPanel.LABEL);
+ passwordLabel.add(new AttributeModifier("for", FORM_SUFFIX + "password"));
+
+ ((PasswordTextField) passwordField.getField()).setResetPassword(true);
+ form.add(passwordField);
+
+ confirmPasswordField = new AjaxPasswordFieldPanel("confirmPassword",
+ getString("confirmPassword"), new Model<>());
+ confirmPasswordField.setRequired(true);
+ confirmPasswordField.setMarkupId("confirmPassword");
+ confirmPasswordField.setPlaceholder("confirmPassword");
+
+ Label confirmPasswordLabel = (Label) confirmPasswordField.get(AbstractFieldPanel.LABEL);
+ confirmPasswordLabel.add(new AttributeModifier("for", FORM_SUFFIX + "confirmPassword"));
+
+ ((PasswordTextField) confirmPasswordField.getField()).setResetPassword(true);
+ form.add(confirmPasswordField);
+
+ form.add(new EqualPasswordInputValidator(passwordField.getField(), confirmPasswordField.getField()));
+
+ captcha = new CaptchaPanel<>(EnduserConstants.CONTENT_PANEL);
+ captcha.setOutputMarkupPlaceholderTag(true);
+
+ form.add(new CardPanel.Builder<CaptchaPanel<Void>>()
+ .setName("captcha")
+ .setComponent(captcha)
+ .isVisible(SyncopeWebApplication.get().isCaptchaEnabled()).build("captchaPanelCard"));
+
+ AjaxButton submitButton = new AjaxButton("submit", new Model<>(getString("submit"))) {
+
+ private static final long serialVersionUID = 429178684321093953L;
+
+ @Override
+ protected void onSubmit(final AjaxRequestTarget target) {
+ doSubmit(target, passwordField);
+ }
+
+ @Override
+ protected void onError(final AjaxRequestTarget target) {
+ notificationPanel.refresh(target);
+ }
+ };
+ form.add(submitButton);
+ form.setDefaultButton(submitButton);
+
+ Button cancel = new Button("cancel") {
+
+ private static final long serialVersionUID = 3669569969172391336L;
+
+ @Override
+ public void onSubmit() {
+ doCancel();
+ }
+ };
+ cancel.setOutputMarkupId(true);
+ cancel.setDefaultFormProcessing(false);
+ form.add(cancel);
+ }
+
+ public StatelessForm<Void> getForm() {
+ return form;
+ }
+
+ public AjaxPasswordFieldPanel getPasswordField() {
+ return passwordField;
+ }
+
+ public AjaxPasswordFieldPanel getConfirmPasswordField() {
+ return confirmPasswordField;
+ }
+
+ protected abstract void doSubmit(AjaxRequestTarget target, AjaxPasswordFieldPanel passwordField);
+
+ protected abstract void doCancel();
+
+ protected abstract UserTO getLoggedUser();
+}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel.java
deleted file mode 100644
index 595ff0c..0000000
--- a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel.java
+++ /dev/null
@@ -1,217 +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.enduser.panels;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.stream.Collectors;
-import org.apache.syncope.client.enduser.SyncopeEnduserSession;
-import org.apache.syncope.client.enduser.SyncopeWebApplication;
-import org.apache.syncope.client.enduser.pages.BaseEnduserWebPage;
-import org.apache.syncope.client.enduser.rest.UserSelfRestClient;
-import org.apache.syncope.client.enduser.wizards.any.CaptchaPanel;
-import org.apache.syncope.client.ui.commons.Constants;
-import org.apache.syncope.client.ui.commons.DomainDropDown;
-import org.apache.syncope.common.keymaster.client.api.DomainOps;
-import org.apache.syncope.common.keymaster.client.api.model.Domain;
-import org.apache.syncope.common.lib.SyncopeClientException;
-import org.apache.syncope.common.lib.SyncopeConstants;
-import org.apache.syncope.common.lib.to.SecurityQuestionTO;
-import org.apache.syncope.common.rest.api.service.SecurityQuestionService;
-import org.apache.wicket.PageReference;
-import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
-import org.apache.wicket.ajax.markup.html.AjaxLink;
-import org.apache.wicket.ajax.markup.html.form.AjaxButton;
-import org.apache.wicket.event.IEventSource;
-import org.apache.wicket.markup.html.form.Button;
-import org.apache.wicket.markup.html.form.TextField;
-import org.apache.wicket.markup.html.panel.Panel;
-import org.apache.wicket.model.LoadableDetachableModel;
-import org.apache.wicket.model.Model;
-import org.apache.wicket.model.PropertyModel;
-import org.apache.wicket.request.mapper.parameter.PageParameters;
-import org.apache.wicket.spring.injection.annot.SpringBean;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class SelfPwdResetPanel extends Panel implements IEventSource {
-
- private static final long serialVersionUID = -2841210052053545578L;
-
- private static final Logger LOG = LoggerFactory.getLogger(SelfPwdResetPanel.class);
-
- @SpringBean
- private DomainOps domainOps;
-
- private final LoadableDetachableModel<List<String>> domains = new LoadableDetachableModel<List<String>>() {
-
- private static final long serialVersionUID = 4659376149825914247L;
-
- @Override
- protected List<String> load() {
- List<String> current = new ArrayList<>();
- current.addAll(domainOps.list().stream().map(Domain::getKey).sorted().collect(Collectors.toList()));
- current.add(0, SyncopeConstants.MASTER_DOMAIN);
- return current;
- }
- };
-
- private String usernameText;
-
- private String securityAnswerText;
-
- private final TextField<String> securityQuestion;
-
- private final CaptchaPanel<Void> captcha;
-
- public SelfPwdResetPanel(final String id, final PageReference pageRef) {
- super(id);
-
- DomainDropDown domainSelect = new DomainDropDown("domain", domains);
- domainSelect.add(new AjaxFormComponentUpdatingBehavior(Constants.ON_BLUR) {
-
- private static final long serialVersionUID = -1107858522700306810L;
-
- @Override
- protected void onUpdate(final AjaxRequestTarget target) {
- // nothing to do
- }
- }).add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
-
- private static final long serialVersionUID = -1107858522700306810L;
-
- @Override
- protected void onUpdate(final AjaxRequestTarget target) {
- // nothing to do
- }
- });
- add(domainSelect);
-
- TextField<String> username =
- new TextField<>("username", new PropertyModel<>(this, "usernameText"), String.class);
- username.add(new AjaxFormComponentUpdatingBehavior(Constants.ON_BLUR) {
-
- private static final long serialVersionUID = -1107858522700306810L;
-
- @Override
- protected void onUpdate(final AjaxRequestTarget target) {
- loadSecurityQuestion(pageRef, target);
- }
- });
- username.setRequired(true);
- add(username);
-
- securityQuestion =
- new TextField<>("securityQuestion", new PropertyModel<>(Model.of(), "content"), String.class);
- securityQuestion.setOutputMarkupId(true);
- securityQuestion.setEnabled(false);
- add(securityQuestion);
-
- AjaxLink<Void> reloadLink = new AjaxLink<>("reloadLink") {
-
- private static final long serialVersionUID = -817438685948164787L;
-
- @Override
- public void onClick(final AjaxRequestTarget target) {
- loadSecurityQuestion(pageRef, target);
- }
- };
- add(reloadLink);
-
- TextField<String> securityAnswer =
- new TextField<>("securityAnswer", new PropertyModel<>(this, "securityAnswerText"), String.class);
- securityAnswer.add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
-
- private static final long serialVersionUID = -1107858522700306810L;
-
- @Override
- protected void onUpdate(final AjaxRequestTarget target) {
- // do nothing
- }
- });
- securityAnswer.setRequired(true);
- add(securityAnswer);
-
- captcha = new CaptchaPanel<>("captchaPanel");
- captcha.setOutputMarkupPlaceholderTag(true);
- captcha.setVisible(SyncopeWebApplication.get().isCaptchaEnabled());
- add(captcha);
-
- AjaxButton submitButton = new AjaxButton("submit") {
-
- private static final long serialVersionUID = 4284361595033427185L;
-
- @Override
- protected void onSubmit(final AjaxRequestTarget target) {
- boolean checked = true;
- if (SyncopeWebApplication.get().isCaptchaEnabled()) {
- checked = captcha.captchaCheck();
- }
- if (!checked) {
- SyncopeEnduserSession.get().error(getString(Constants.CAPTCHA_ERROR));
- ((BaseEnduserWebPage) pageRef.getPage()).getNotificationPanel().refresh(target);
- } else {
- try {
- UserSelfRestClient.requestPasswordReset(usernameText, securityAnswerText);
- PageParameters parameters = new PageParameters();
- parameters.add(Constants.NOTIFICATION_MSG_PARAM, getString("self.pwd.reset.success"));
- setResponsePage(getApplication().getHomePage(), parameters);
- } catch (SyncopeClientException sce) {
- LOG.error("Unable to reset password of [{}]", usernameText, sce);
- SyncopeEnduserSession.get().onException(sce);
- ((BaseEnduserWebPage) pageRef.getPage()).getNotificationPanel().refresh(target);
- }
- }
- }
-
- };
- submitButton.setOutputMarkupId(true);
- submitButton.setDefaultFormProcessing(false);
- add(submitButton);
-
- Button cancel = new Button("cancel") {
-
- private static final long serialVersionUID = 3669569969172391336L;
-
- @Override
- public void onSubmit() {
- setResponsePage(getApplication().getHomePage());
- }
-
- };
- cancel.setOutputMarkupId(true);
- cancel.setDefaultFormProcessing(false);
- add(cancel);
- }
-
- protected void loadSecurityQuestion(final PageReference pageRef, final AjaxRequestTarget target) {
- try {
- SecurityQuestionTO securityQuestionTO = SyncopeEnduserSession.get().getService(
- SecurityQuestionService.class).readByUser(usernameText);
- // set security question field model
- securityQuestion.setModel(Model.of(securityQuestionTO.getContent()));
- target.add(securityQuestion);
- } catch (Exception e) {
- LOG.error("Unable to get security question for [{}]", usernameText, e);
- SyncopeEnduserSession.get().onException(e);
- ((BaseEnduserWebPage) pageRef.getPage()).getNotificationPanel().refresh(target);
- }
- }
-}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/Sidebar.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/Sidebar.java
new file mode 100644
index 0000000..bd31754
--- /dev/null
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/Sidebar.java
@@ -0,0 +1,200 @@
+/*
+ * 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.enduser.panels;
+
+import java.util.List;
+import java.util.stream.StreamSupport;
+import org.apache.syncope.client.enduser.BookmarkablePageLinkBuilder;
+import org.apache.syncope.client.enduser.SyncopeWebApplication;
+import org.apache.syncope.client.enduser.SyncopeEnduserSession;
+import org.apache.syncope.client.enduser.pages.BasePage;
+import org.apache.syncope.client.enduser.pages.Dashboard;
+import org.apache.syncope.client.enduser.pages.EditChangePassword;
+import org.apache.syncope.client.enduser.pages.EditSecurityQuestion;
+import org.apache.syncope.client.enduser.pages.EditUser;
+import org.apache.syncope.client.ui.commons.annotations.ExtPage;
+import org.apache.wicket.AttributeModifier;
+import org.apache.wicket.Component;
+import org.apache.wicket.Page;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.behavior.Behavior;
+import org.apache.wicket.markup.ComponentTag;
+import org.apache.wicket.markup.head.IHeaderResponse;
+import org.apache.wicket.markup.head.OnDomReadyHeaderItem;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.link.BookmarkablePageLink;
+import org.apache.wicket.markup.html.link.Link;
+import org.apache.wicket.markup.html.list.ListItem;
+import org.apache.wicket.markup.html.list.ListView;
+import org.apache.wicket.markup.html.panel.Panel;
+
+public class Sidebar extends Panel {
+
+ private static final long serialVersionUID = 8091307811313529503L;
+
+ protected WebMarkupContainer dashboardLIContainer;
+
+ protected WebMarkupContainer profileULContainer;
+
+ protected WebMarkupContainer profileLIContainer;
+
+ public Sidebar(
+ final String id,
+ final PageReference pageRef,
+ final List<Class<? extends BasePage>> extPageClasses) {
+
+ super(id);
+
+ buildBaseSidebar();
+
+ // set 'active' menu item for everything but extensions
+ // 1. check if current class is set to top-level menu
+ WebMarkupContainer containingLI = null;
+ if (dashboardLIContainer.getId().equals(
+ getLIContainerId(pageRef.getPage().getClass().getSimpleName().toLowerCase()))) {
+
+ containingLI = dashboardLIContainer;
+ }
+ // 2. if not, check if it is under 'Configuration'
+ if (containingLI == null) {
+ containingLI = (WebMarkupContainer) profileULContainer.get(
+ getLIContainerId(pageRef.getPage().getClass().getSimpleName().toLowerCase()));
+ }
+ // 3. when found, set CSS coordinates for menu
+ if (containingLI != null) {
+ StreamSupport.stream(containingLI.spliterator(), false).filter(Link.class::isInstance).
+ forEach(child -> child.add(new Behavior() {
+
+ private static final long serialVersionUID = -5775607340182293596L;
+
+ @Override
+ public void onComponentTag(final Component component, final ComponentTag tag) {
+ tag.append("class", "active", " ");
+ }
+ }));
+
+ if (profileULContainer.getId().equals(containingLI.getParent().getId())) {
+ profileULContainer.add(new Behavior() {
+
+ private static final long serialVersionUID = 3109256773218160485L;
+
+ @Override
+ public void renderHead(final Component component, final IHeaderResponse response) {
+ response.render(OnDomReadyHeaderItem.forScript(
+ "$('#profileLink').addClass('active')"));
+ }
+
+ @Override
+ public void onComponentTag(final Component component, final ComponentTag tag) {
+ tag.put("class", "nav nav-treeview");
+ tag.put("style", "display: block;");
+ }
+ });
+
+ profileLIContainer.add(new Behavior() {
+
+ private static final long serialVersionUID = 3109256773218160485L;
+
+ @Override
+ public void onComponentTag(final Component component, final ComponentTag tag) {
+ tag.put("class", "nav-item has-treeview menu-open");
+ }
+ });
+ }
+ }
+
+ ListView<Class<? extends BasePage>> extPages =
+ new ListView<Class<? extends BasePage>>("extPages", extPageClasses) {
+
+ private static final long serialVersionUID = 4949588177564901031L;
+
+ @Override
+ protected void populateItem(final ListItem<Class<? extends BasePage>> item) {
+ WebMarkupContainer containingLI = new WebMarkupContainer("extPageLI");
+ item.add(containingLI);
+
+ ExtPage ann = item.getModelObject().getAnnotation(ExtPage.class);
+
+ BookmarkablePageLink<Page> link = new BookmarkablePageLink<>("extPage", item.getModelObject());
+
+ link.add(new Label("extPageLabel", ann.label()));
+
+ if (item.getModelObject().equals(pageRef.getPage().getClass())) {
+ link.add(new Behavior() {
+
+ private static final long serialVersionUID = 1469628524240283489L;
+
+ @Override
+ public void renderHead(final Component component, final IHeaderResponse response) {
+ response.render(OnDomReadyHeaderItem.forScript(
+ "$('#extensionsLink').addClass('active')"));
+ }
+
+ @Override
+ public void onComponentTag(final Component component, final ComponentTag tag) {
+ tag.append("class", "active", " ");
+ }
+ });
+ }
+ containingLI.add(link);
+
+ Label extPageIcon = new Label("extPageIcon");
+ extPageIcon.add(new AttributeModifier("class", "nav-icon " + ann.icon()));
+ link.add(extPageIcon);
+ }
+ };
+
+ add(extPages.setRenderBodyOnly(true).setOutputMarkupId(true));
+ }
+
+ protected void buildBaseSidebar() {
+ dashboardLIContainer = new WebMarkupContainer(getLIContainerId("dashboard"));
+ add(dashboardLIContainer);
+ dashboardLIContainer.add(BookmarkablePageLinkBuilder.build(
+ "home", SyncopeWebApplication.get().getPageClass("profile", Dashboard.class)));
+
+ profileLIContainer = new WebMarkupContainer(getLIContainerId("profile"));
+ add(profileLIContainer);
+ profileULContainer = new WebMarkupContainer(getULContainerId("profile"));
+ profileLIContainer.add(profileULContainer);
+
+ WebMarkupContainer liContainer = new WebMarkupContainer(getLIContainerId("edituser"));
+ profileULContainer.add(liContainer);
+ liContainer.add(BookmarkablePageLinkBuilder.build("edituser", EditUser.class));
+
+ liContainer = new WebMarkupContainer(getLIContainerId("editchangepassword"));
+ profileULContainer.add(liContainer);
+ liContainer.add(BookmarkablePageLinkBuilder.build("editchangepassword", EditChangePassword.class));
+
+ liContainer = new WebMarkupContainer(getLIContainerId("editsecurityquestion"));
+ profileULContainer.add(liContainer);
+ liContainer.add(BookmarkablePageLinkBuilder.build("editsecurityquestion", EditSecurityQuestion.class));
+ liContainer.setOutputMarkupPlaceholderTag(true);
+ liContainer.setVisible(SyncopeEnduserSession.get().getPlatformInfo().isPwdResetRequiringSecurityQuestions());
+ }
+
+ protected String getLIContainerId(final String linkId) {
+ return linkId + "LI";
+ }
+
+ protected String getULContainerId(final String linkId) {
+ return linkId + "UL";
+ }
+}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/UserFormPanel.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/UserFormPanel.java
new file mode 100644
index 0000000..0a91fa7
--- /dev/null
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/UserFormPanel.java
@@ -0,0 +1,161 @@
+/*
+ * 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.enduser.panels;
+
+import java.util.List;
+import org.apache.syncope.client.enduser.SyncopeEnduserSession;
+import org.apache.syncope.client.enduser.SyncopeWebApplication;
+import org.apache.syncope.client.enduser.commons.EnduserConstants;
+import org.apache.syncope.client.enduser.layout.UserFormLayoutInfo;
+import org.apache.syncope.client.enduser.pages.BasePage;
+import org.apache.syncope.client.enduser.pages.Dashboard;
+import org.apache.syncope.client.enduser.pages.SelfResult;
+import org.apache.syncope.client.enduser.panels.any.Details;
+import org.apache.syncope.client.enduser.panels.any.UserDetails;
+import org.apache.syncope.client.enduser.rest.UserSelfRestClient;
+import org.apache.syncope.client.ui.commons.Constants;
+import org.apache.syncope.client.ui.commons.layout.UserForm;
+import org.apache.syncope.client.ui.commons.panels.WizardModalPanel;
+import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
+import org.apache.syncope.client.ui.commons.wizards.ModalPanelBuilder;
+import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
+import org.apache.syncope.client.ui.commons.wizards.any.UserWrapper;
+import org.apache.syncope.common.lib.AnyOperations;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.request.UserUR;
+import org.apache.syncope.common.lib.to.ProvisioningResult;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.event.IEventSink;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
+
+public class UserFormPanel extends AnyFormPanel implements UserForm {
+
+ private static final long serialVersionUID = 6763365006334514387L;
+
+ private final UserSelfRestClient userSelfRestClient = new UserSelfRestClient();
+
+ public UserFormPanel(
+ final String id,
+ final UserTO userTO,
+ final List<String> anyTypeClasses,
+ final UserFormLayoutInfo formLayoutInfo,
+ final PageReference pageReference) {
+ super(id, new UserWrapper(userTO), anyTypeClasses, formLayoutInfo, pageReference);
+
+ UserWrapper modelObj = newModelObject();
+ buildLayout(modelObj);
+ }
+
+ public UserFormPanel(
+ final String id,
+ final UserTO previousUserTO,
+ final UserTO userTO,
+ final List<String> anyTypeClasses,
+ final UserFormLayoutInfo formLayoutInfo,
+ final PageReference pageReference) {
+ super(id, new UserWrapper(previousUserTO, userTO), anyTypeClasses, formLayoutInfo, pageReference);
+
+ UserWrapper modelObj = newModelObject();
+ setFormModel(modelObj);
+ buildLayout(modelObj);
+
+ }
+
+ @Override
+ protected Details<UserTO> addOptionalDetailsPanel(final UserWrapper modelObject) {
+ return new UserDetails(
+ EnduserConstants.CONTENT_PANEL,
+ UserWrapper.class.cast(modelObject),
+ false,
+ false,
+ pageRef);
+ }
+
+ @Override
+ protected void onFormSubmit(final AjaxRequestTarget target) {
+ // captcha check
+ boolean checked = true;
+ if (SyncopeWebApplication.get().isCaptchaEnabled()) {
+ checked = captcha.check();
+ }
+ if (!checked) {
+ SyncopeEnduserSession.get().error(getString(Constants.CAPTCHA_ERROR));
+ ((BasePage) pageRef.getPage()).getNotificationPanel().refresh(target);
+ } else {
+ ProvisioningResult<UserTO> result;
+ PageParameters parameters = new PageParameters();
+ try {
+ AnyWrapper<UserTO> updatedWrapper = form.getModelObject();
+ UserTO userTO = updatedWrapper.getInnerObject();
+
+ fixPlainAndVirAttrs(userTO, getOriginalItem().getInnerObject());
+ UserUR req = AnyOperations.diff(userTO, getOriginalItem().getInnerObject(), false);
+
+ // update just if it is changed
+ if (req.isEmpty()) {
+ result = new ProvisioningResult<>();
+ result.setEntity(userTO);
+ } else {
+ result = userSelfRestClient.update(getOriginalItem().getInnerObject().getETagValue(), req);
+ LOG.debug("User {} has been modified", result.getEntity().getUsername());
+ }
+ parameters.add(EnduserConstants.STATUS, Constants.OPERATION_SUCCEEDED);
+ parameters.add(Constants.NOTIFICATION_TITLE_PARAM, getString("self.profile.change.success"));
+ parameters.add(Constants.NOTIFICATION_MSG_PARAM, getString("self.profile.change.success.msg"));
+ } catch (SyncopeClientException sce) {
+ parameters.add(EnduserConstants.STATUS, Constants.ERROR);
+ parameters.add(Constants.NOTIFICATION_TITLE_PARAM, getString("self.profile.change.error"));
+ parameters.add(Constants.NOTIFICATION_MSG_PARAM, getString("self.profile.change.error.msg"));
+ SyncopeEnduserSession.get().onException(sce);
+ ((BasePage) pageRef.getPage()).getNotificationPanel().refresh(target);
+ }
+ parameters.add(
+ EnduserConstants.LANDING_PAGE,
+ SyncopeWebApplication.get().getPageClass("profile", Dashboard.class).getName());
+ setResponsePage(SelfResult.class, parameters);
+ }
+ }
+
+ @Override
+ public IEventSink getEventSink() {
+ return null;
+ }
+
+ @Override
+ public ModalPanelBuilder<AnyWrapper<UserTO>> setEventSink(final IEventSink eventSink) {
+ return null;
+ }
+
+ @Override
+ public ModalPanelBuilder<AnyWrapper<UserTO>> setItem(final AnyWrapper<UserTO> item) {
+ return null;
+ }
+
+ @Override
+ public AnyWrapper<UserTO> getDefaultItem() {
+ return null;
+ }
+
+ @Override
+ public WizardModalPanel<AnyWrapper<UserTO>> build(final String id, final int index, final AjaxWizard.Mode mode) {
+ return null;
+ }
+}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/UserSelfFormPanel.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/UserSelfFormPanel.java
new file mode 100644
index 0000000..a3a610d
--- /dev/null
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/UserSelfFormPanel.java
@@ -0,0 +1,135 @@
+/*
+ * 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.enduser.panels;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.enduser.SyncopeWebApplication;
+import org.apache.syncope.client.enduser.SyncopeEnduserSession;
+import org.apache.syncope.client.enduser.layout.UserFormLayoutInfo;
+import org.apache.syncope.client.enduser.pages.BasePage;
+import org.apache.syncope.client.enduser.pages.Login;
+import org.apache.syncope.client.enduser.pages.SelfResult;
+import org.apache.syncope.client.enduser.panels.any.Details;
+import org.apache.syncope.client.enduser.panels.any.SelfUserDetails;
+import org.apache.syncope.client.enduser.rest.UserSelfRestClient;
+import org.apache.syncope.client.ui.commons.Constants;
+import org.apache.syncope.client.ui.commons.pages.BaseWebPage;
+import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
+import org.apache.syncope.client.ui.commons.wizards.any.UserWrapper;
+import org.apache.syncope.common.lib.EntityTOUtils;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.request.UserCR;
+import org.apache.syncope.common.lib.to.ProvisioningResult;
+import org.apache.syncope.common.lib.to.SecurityQuestionTO;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.common.rest.api.service.SecurityQuestionService;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.markup.html.form.TextField;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
+import java.util.List;
+import org.apache.syncope.client.enduser.commons.EnduserConstants;
+
+public class UserSelfFormPanel extends UserFormPanel {
+
+ private static final long serialVersionUID = 6763365006334514387L;
+
+ private final UserSelfRestClient userSelfRestClient = new UserSelfRestClient();
+
+ private TextField<String> securityQuestion;
+
+ private String usernameText;
+
+ public UserSelfFormPanel(
+ final String id,
+ final UserTO previousUserTO,
+ final UserTO userTO,
+ final List<String> anyTypeClasses,
+ final UserFormLayoutInfo formLayoutInfo,
+ final PageReference pageReference) {
+ super(id, previousUserTO, userTO, anyTypeClasses, formLayoutInfo, pageReference);
+ }
+
+ @Override
+ protected Details<UserTO> addOptionalDetailsPanel(final UserWrapper modelObject) {
+ return new SelfUserDetails(
+ EnduserConstants.CONTENT_PANEL,
+ UserWrapper.class.cast(modelObject),
+ false,
+ false,
+ UserFormLayoutInfo.class.cast(formLayoutInfo).isPasswordManagement(),
+ pageRef);
+ }
+
+ @Override
+ protected void onFormSubmit(final AjaxRequestTarget target) {
+ // captcha check
+ boolean checked = true;
+ if (SyncopeWebApplication.get().isCaptchaEnabled()) {
+ checked = captcha.check();
+ }
+ if (!checked) {
+ SyncopeEnduserSession.get().error(getString(Constants.CAPTCHA_ERROR));
+ ((BasePage) pageRef.getPage()).getNotificationPanel().refresh(target);
+ } else {
+ ProvisioningResult<UserTO> result;
+ PageParameters parameters = new PageParameters();
+ try {
+ AnyWrapper<UserTO> updatedWarapper = form.getModelObject();
+ UserTO userTO = updatedWarapper.getInnerObject();
+
+ UserCR req = new UserCR();
+ EntityTOUtils.toAnyCR(userTO, req);
+ req.setStorePassword(updatedWarapper instanceof UserWrapper
+ ? UserWrapper.class.cast(updatedWarapper).isStorePasswordInSyncope()
+ : StringUtils.isNotBlank(userTO.getPassword()));
+
+ result = userSelfRestClient.create(req, true);
+ LOG.debug("User {} has been created", result.getEntity().getUsername());
+
+ parameters.add(EnduserConstants.STATUS, Constants.OPERATION_SUCCEEDED);
+ parameters.add(Constants.NOTIFICATION_TITLE_PARAM, getString("self.profile.change.success"));
+ parameters.add(Constants.NOTIFICATION_MSG_PARAM, getString("self.profile.change.success.msg"));
+ } catch (SyncopeClientException sce) {
+ parameters.add(EnduserConstants.STATUS, Constants.ERROR);
+ parameters.add(Constants.NOTIFICATION_TITLE_PARAM, getString("self.profile.change.error"));
+ parameters.add(Constants.NOTIFICATION_MSG_PARAM, getString("self.profile.change.error.msg"));
+ SyncopeEnduserSession.get().onException(sce);
+ ((BasePage) pageRef.getPage()).getNotificationPanel().refresh(target);
+ }
+ parameters.add(EnduserConstants.LANDING_PAGE, Login.class);
+ setResponsePage(SelfResult.class, parameters);
+ }
+ }
+
+ protected void loadSecurityQuestion(final PageReference pageRef, final AjaxRequestTarget target) {
+ try {
+ SecurityQuestionTO securityQuestionTO = SyncopeEnduserSession.get().getService(
+ SecurityQuestionService.class).readByUser(usernameText);
+ // set security question field model
+ securityQuestion.setModel(Model.of(securityQuestionTO.getContent()));
+ target.add(securityQuestion);
+ } catch (Exception e) {
+ LOG.error("Unable to get security question for [{}]", usernameText, e);
+ SyncopeEnduserSession.get().onException(e);
+ ((BaseWebPage) pageRef.getPage()).getNotificationPanel().refresh(target);
+ }
+ }
+}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/AbstractAttrs.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/any/AbstractAttrs.java
similarity index 85%
rename from client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/AbstractAttrs.java
rename to client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/any/AbstractAttrs.java
index be2c63d..9f6e4ec 100644
--- a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/AbstractAttrs.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/any/AbstractAttrs.java
@@ -16,41 +16,41 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.syncope.client.enduser.wizards.any;
+package org.apache.syncope.client.enduser.panels.any;
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.cxf.common.util.StringUtils;
import org.apache.syncope.client.enduser.layout.CustomizationOption;
import org.apache.syncope.client.enduser.rest.SchemaRestClient;
import org.apache.syncope.client.enduser.rest.SyncopeRestClient;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxPalettePanel;
import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
-import org.apache.syncope.common.lib.to.SchemaTO;
-import org.apache.syncope.common.lib.to.AnyTO;
import org.apache.syncope.common.lib.Attr;
+import org.apache.syncope.common.lib.to.AnyTO;
import org.apache.syncope.common.lib.to.MembershipTO;
+import org.apache.syncope.common.lib.to.SchemaTO;
import org.apache.syncope.common.lib.types.SchemaType;
-import org.apache.wicket.PageReference;
import org.apache.wicket.WicketRuntimeException;
import org.apache.wicket.core.util.lang.PropertyResolver;
-import org.apache.wicket.extensions.wizard.WizardModel.ICondition;
-import org.apache.wicket.extensions.wizard.WizardStep;
-import org.apache.wicket.markup.head.IHeaderResponse;
-import org.apache.wicket.markup.head.OnDomReadyHeaderItem;
+import org.apache.wicket.event.IEvent;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.util.ListModel;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
-public abstract class AbstractAttrs<S extends SchemaTO> extends WizardStep implements ICondition {
+public abstract class AbstractAttrs<S extends SchemaTO> extends Panel {
private static final long serialVersionUID = -5387344116983102292L;
+ protected static final String FORM_SUFFIX = "form_";
+
protected final Comparator<Attr> attrComparator = new AttrComparator();
protected final AnyTO anyTO;
@@ -68,18 +68,21 @@
private final List<String> anyTypeClasses;
public AbstractAttrs(
+ final String id,
final AnyWrapper<?> modelObject,
final List<String> anyTypeClasses,
final Map<String, CustomizationOption> whichAttrs) {
- super();
+ super(id);
this.anyTypeClasses = anyTypeClasses;
- this.attrs = new ListModel<>(List.of());
- this.membershipTOs = new ListModel<>(List.of());
+ this.attrs = new ListModel<>(Collections.emptyList());
+ this.membershipTOs = new ListModel<>(Collections.emptyList());
this.setOutputMarkupId(true);
this.anyTO = modelObject.getInnerObject();
this.whichAttrs = whichAttrs;
+
+ evaluate();
}
private List<Attr> loadAttrs() {
@@ -99,9 +102,8 @@
for (MembershipTO membership : (List<MembershipTO>) PropertyResolver.getPropertyField(
"memberships", anyTO).get(anyTO)) {
- setSchemas(
- Pair.of(membership.getGroupKey(), membership.getGroupName()),
- getMembershipAuxClasses(membership));
+ setSchemas(Pair.of(membership.getGroupKey(), membership.getGroupName()), getMembershipAuxClasses(
+ membership, anyTO.getType()));
setAttrs(membership);
if (AbstractAttrs.this instanceof PlainAttrs && !membership.getPlainAttrs().isEmpty()) {
@@ -142,7 +144,7 @@
: groupName + '#')
+ schema;
return whichAttrs.get(schemaName) == null
- ? List.of()
+ ? Collections.emptyList()
: whichAttrs.get(schemaName).getDefaultValues();
}
@@ -185,15 +187,8 @@
allSchemas.forEach(schemaTO -> scs.put(schemaTO.getKey(), schemaTO));
}
- @Override
- public void renderHead(final IHeaderResponse response) {
- super.renderHead(response);
- if (org.apache.cxf.common.util.CollectionUtils.isEmpty(attrs.getObject())
- && org.apache.cxf.common.util.CollectionUtils.isEmpty(membershipTOs.getObject())) {
- response.render(OnDomReadyHeaderItem.forScript(
- String.format("$('#emptyPlaceholder').append(\"%s\"); $('#attributes').hide();",
- getString("attribute.empty.list"))));
- }
+ public boolean isPanelVisible() {
+ return !attrs.getObject().isEmpty() || !membershipTOs.getObject().isEmpty();
}
protected abstract void setAttrs();
@@ -204,27 +199,26 @@
protected abstract List<Attr> getAttrsFromTO(MembershipTO membershipTO);
- protected static List<String> getMembershipAuxClasses(final MembershipTO membershipTO) {
+ protected static List<String> getMembershipAuxClasses(final MembershipTO membershipTO, final String anyType) {
try {
return SyncopeRestClient.searchUserTypeExtensions(membershipTO.getGroupName());
} catch (Exception e) {
- return List.of();
+ return Collections.emptyList();
}
}
@Override
+ protected void onInitialize() {
+ evaluate();
+ super.onInitialize();
+ }
+
public boolean evaluate() {
this.attrs.setObject(loadAttrs());
this.membershipTOs.setObject(loadMembershipAttrs());
return !attrs.getObject().isEmpty() || !membershipTOs.getObject().isEmpty();
}
- public PageReference getPageReference() {
- // SYNCOPE-1213
- // default implementation does not require to pass page reference, override this method of want otherwise
- return null;
- }
-
private class AttrComparator implements Comparator<Attr>, Serializable {
private static final long serialVersionUID = -5105030477767941060L;
@@ -253,6 +247,16 @@
}
}
+ @Override
+ public void onEvent(final IEvent<?> event) {
+ super.onEvent(event);
+ if (event.getPayload() instanceof AjaxPalettePanel.UpdateActionEvent) {
+ evaluate();
+ AjaxPalettePanel.UpdateActionEvent updateEvent = (AjaxPalettePanel.UpdateActionEvent) event.getPayload();
+ updateEvent.getTarget().add(this);
+ }
+ }
+
public static class Schemas extends Panel {
private static final long serialVersionUID = -2447602429647965090L;
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/DerAttrs.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/any/DerAttrs.java
similarity index 90%
rename from client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/DerAttrs.java
rename to client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/any/DerAttrs.java
index 952b834..fea60ce 100644
--- a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/DerAttrs.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/any/DerAttrs.java
@@ -16,27 +16,28 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.syncope.client.enduser.wizards.any;
+package org.apache.syncope.client.enduser.panels.any;
-import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
import org.apache.syncope.client.enduser.SyncopeEnduserSession;
import org.apache.syncope.client.enduser.layout.CustomizationOption;
-import org.apache.syncope.client.ui.commons.wicket.markup.html.bootstrap.tabs.Accordion;
import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.ui.commons.wicket.markup.html.bootstrap.tabs.Accordion;
+import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
+import org.apache.syncope.common.lib.Attr;
import org.apache.syncope.common.lib.EntityTOUtils;
import org.apache.syncope.common.lib.to.AnyTO;
-import org.apache.syncope.common.lib.Attr;
import org.apache.syncope.common.lib.to.DerSchemaTO;
import org.apache.syncope.common.lib.to.GroupableRelatableTO;
import org.apache.syncope.common.lib.to.MembershipTO;
import org.apache.syncope.common.lib.types.SchemaType;
import org.apache.wicket.extensions.markup.html.tabs.AbstractTab;
+import org.apache.wicket.extensions.markup.html.tabs.ITab;
import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.MarkupStream;
import org.apache.wicket.markup.html.WebMarkupContainer;
@@ -47,30 +48,21 @@
import org.apache.wicket.model.ResourceModel;
import org.apache.wicket.model.StringResourceModel;
import org.apache.wicket.model.util.ListModel;
+import java.util.stream.Collectors;
public class DerAttrs extends AbstractAttrs<DerSchemaTO> {
private static final long serialVersionUID = -5387344116983102292L;
public <T extends AnyTO> DerAttrs(
+ final String id,
final AnyWrapper<T> modelObject,
final List<String> anyTypeClasses,
final Map<String, CustomizationOption> whichDerAttrs) {
- super(modelObject, anyTypeClasses, whichDerAttrs);
- setTitleModel(new ResourceModel("attributes.derived"));
+ super(id, modelObject, anyTypeClasses, whichDerAttrs);
- add(new Accordion("derSchemas", List.of(new AbstractTab(
- new ResourceModel("attributes.accordion", "Derived Attributes")) {
-
- private static final long serialVersionUID = 1037272333056449378L;
-
- @Override
- public WebMarkupContainer getPanel(final String panelId) {
- return new DerAttrs.DerSchemas(panelId, schemas, attrs);
- }
- }), Model.of(0)).setOutputMarkupId(true));
-
+ add(new DerAttrs.DerSchemas("derSchemas", schemas, attrs).setOutputMarkupId(true));
add(new ListView<MembershipTO>("membershipsDerSchemas", membershipTOs) {
private static final long serialVersionUID = 6741044372185745296L;
@@ -78,7 +70,7 @@
@Override
protected void populateItem(final ListItem<MembershipTO> item) {
final MembershipTO membershipTO = item.getModelObject();
- item.add(new Accordion("membershipDerSchemas", List.of(new AbstractTab(
+ item.add(new Accordion("membershipDerSchemas", Collections.<ITab>singletonList(new AbstractTab(
new StringResourceModel(
"attributes.membership.accordion",
DerAttrs.this,
@@ -159,7 +151,7 @@
membershipTO.getDerAttrs().addAll(derAttrs);
}
- public static class DerSchemas extends Schemas {
+ public class DerSchemas extends Schemas {
private static final long serialVersionUID = -4730563859116024676L;
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/any/Details.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/any/Details.java
new file mode 100644
index 0000000..23c9bdf
--- /dev/null
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/any/Details.java
@@ -0,0 +1,45 @@
+/*
+ * 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.enduser.panels.any;
+
+import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
+import org.apache.syncope.common.lib.to.AnyTO;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class Details<T extends AnyTO> extends Panel {
+
+ private static final long serialVersionUID = -8995647450549098844L;
+
+ protected static final Logger LOG = LoggerFactory.getLogger(Details.class);
+
+ protected final PageReference pageRef;
+
+ public Details(
+ final String id,
+ final AnyWrapper<T> wrapper,
+ final boolean templateMode,
+ final boolean includeStatusPanel,
+ final PageReference pageRef) {
+ super(id);
+ this.pageRef = pageRef;
+ }
+}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/Groups.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/any/Groups.java
similarity index 71%
rename from client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/Groups.java
rename to client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/any/Groups.java
index 7626f73..5b3912a 100644
--- a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/Groups.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/any/Groups.java
@@ -16,35 +16,79 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.syncope.client.enduser.wizards.any;
+package org.apache.syncope.client.enduser.panels.any;
-import java.util.List;
-import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
import org.apache.syncope.client.enduser.rest.GroupRestClient;
-import org.apache.syncope.client.lib.SyncopeClient;
-import org.apache.syncope.client.ui.commons.Constants;
import org.apache.syncope.client.ui.commons.markup.html.form.AjaxPalettePanel;
-import org.apache.syncope.client.ui.commons.wizards.any.AbstractGroups;
import org.apache.syncope.client.ui.commons.wizards.any.AbstractGroupsModel;
import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
-import org.apache.syncope.common.lib.to.AnyTO;
-import org.apache.syncope.common.lib.to.GroupTO;
-import org.apache.syncope.common.lib.to.GroupableRelatableTO;
-import org.apache.syncope.common.lib.to.MembershipTO;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.event.Broadcast;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.IChoiceRenderer;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.util.ListModel;
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.List;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import org.apache.commons.collections4.ListUtils;
+import org.apache.syncope.client.ui.commons.ajax.markup.html.LabelInfo;
+import org.apache.syncope.client.ui.commons.wizards.any.UserWrapper;
+import org.apache.syncope.common.lib.to.AnyTO;
+import org.apache.syncope.common.lib.to.GroupTO;
+import org.apache.syncope.common.lib.to.GroupableRelatableTO;
+import org.apache.syncope.common.lib.to.MembershipTO;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.panel.Panel;
-public class Groups extends AbstractGroups {
+public class Groups extends Panel {
private static final long serialVersionUID = 552437609667518888L;
+ protected static final int MAX_GROUP_LIST_CARDINALITY = 30;
+
private final EnduserGroupsModel groupsModel;
- public <T extends AnyTO> Groups(final AnyWrapper<T> modelObject) {
- super(modelObject);
+ protected final AnyTO anyTO;
+
+ protected WebMarkupContainer dyngroupsContainer;
+
+ protected WebMarkupContainer dynrealmsContainer;
+
+ protected WebMarkupContainer groupsContainer;
+
+ public <T extends AnyTO> Groups(final String id,
+ final AnyWrapper<T> modelObject,
+ final boolean templateMode) {
+
+ super(id);
+ this.anyTO = modelObject.getInnerObject();
+
+ setOutputMarkupId(true);
+
+ groupsContainer = new WebMarkupContainer("groupsContainer");
+ groupsContainer.setOutputMarkupId(true);
+ groupsContainer.setOutputMarkupPlaceholderTag(true);
+ add(groupsContainer);
+
+ // ------------------
+ // insert changed label if needed
+ // ------------------
+ if (modelObject instanceof UserWrapper
+ && UserWrapper.class.cast(modelObject).getPreviousUserTO() != null
+ && !ListUtils.isEqualList(
+ UserWrapper.class.cast(modelObject).getInnerObject().getMemberships(),
+ UserWrapper.class.cast(modelObject).getPreviousUserTO().getMemberships())) {
+ groupsContainer.add(new LabelInfo("changed", StringUtils.EMPTY));
+ } else {
+ groupsContainer.add(new Label("changed", StringUtils.EMPTY));
+ }
+ // ------------------
+
this.groupsModel = new EnduserGroupsModel();
setOutputMarkupId(true);
@@ -54,7 +98,14 @@
addDynamicRealmsContainer();
}
- @Override
+ private Function<AjaxRequestTarget, Boolean> getEventFunction() {
+ return (Function<AjaxRequestTarget, Boolean> & Serializable) (target) -> {
+ send(Groups.this.getPage(), Broadcast.BREADTH,
+ new AjaxPalettePanel.UpdateActionEvent((UserTO) anyTO, target));
+ return true;
+ };
+ }
+
protected void addGroupsPanel() {
if (anyTO instanceof GroupTO) {
groupsContainer.add(new Label("groups").setVisible(false));
@@ -82,7 +133,7 @@
return choices.getObject().stream().
filter(object -> id.equalsIgnoreCase(object.getGroupName())).findAny().orElse(null);
}
- });
+ }).event(getEventFunction());
groupsContainer.add(builder.setAllowOrder(true).withFilter().build("groups",
new ListModel<MembershipTO>() {
@@ -104,8 +155,7 @@
? groupsModel.getObject()
: GroupRestClient.searchAssignableGroups(
anyTO.getRealm(),
- SyncopeClient.getGroupSearchConditionBuilder().
- isAssignable().and().is(Constants.NAME_FIELD_NAME).equalTo(filter).query(),
+ filter,
1, MAX_GROUP_LIST_CARDINALITY)).stream()
.map(input -> new MembershipTO.Builder(input.getKey())
.groupName(input.getName()).build()).collect(Collectors.toList());
@@ -115,11 +165,9 @@
}
}
- @Override
protected void addDynamicRealmsContainer() {
}
- @Override
protected void addDynamicGroupsContainer() {
}
@@ -167,7 +215,7 @@
@Override
public List<String> getDynMemberships() {
- return List.of();
+ return Collections.emptyList();
}
/**
@@ -193,4 +241,7 @@
}
}
}
+
+ public interface SerializableFunction extends Function<AjaxRequestTarget, Boolean>, Serializable {
+ }
}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/PlainAttrs.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/any/PlainAttrs.java
similarity index 75%
rename from client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/PlainAttrs.java
rename to client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/any/PlainAttrs.java
index 281ca92..a25c76d 100644
--- a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/PlainAttrs.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/any/PlainAttrs.java
@@ -16,113 +16,86 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.syncope.client.enduser.wizards.any;
+package org.apache.syncope.client.enduser.panels.any;
import java.util.ArrayList;
-import org.apache.syncope.client.ui.commons.wizards.any.UserWrapper;
-import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.FastDateFormat;
import org.apache.syncope.client.enduser.layout.CustomizationOption;
-import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDateFieldPanel;
import org.apache.syncope.client.enduser.markup.html.form.BinaryFieldPanel;
import org.apache.syncope.client.enduser.markup.html.form.MultiFieldPanel;
-import org.apache.syncope.client.ui.commons.markup.html.form.EncryptedFieldPanel;
import org.apache.syncope.client.ui.commons.SchemaUtils;
+import org.apache.syncope.client.ui.commons.wicket.markup.html.bootstrap.tabs.Accordion;
+import org.apache.syncope.client.ui.commons.wizards.any.UserWrapper;
+import org.apache.syncope.common.lib.Attr;
+import org.apache.syncope.common.lib.Attributable;
+import org.apache.syncope.common.lib.EntityTOUtils;
+import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.lib.types.AttrSchemaType;
+import org.apache.syncope.common.lib.types.SchemaType;
+import org.apache.wicket.AttributeModifier;
+import org.apache.wicket.extensions.markup.html.tabs.AbstractTab;
+import org.apache.wicket.extensions.markup.html.tabs.ITab;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.form.IChoiceRenderer;
+import org.apache.wicket.markup.html.list.ListItem;
+import org.apache.wicket.markup.html.list.ListView;
+import org.apache.wicket.model.util.ListModel;
+import java.util.stream.Collectors;
+import org.apache.syncope.client.enduser.SyncopeEnduserSession;
import org.apache.syncope.client.ui.commons.markup.html.form.AbstractFieldPanel;
import org.apache.syncope.client.ui.commons.markup.html.form.AjaxCheckBoxPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDateFieldPanel;
import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDateTimeFieldPanel;
import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
import org.apache.syncope.client.ui.commons.markup.html.form.AjaxSpinnerFieldPanel;
import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.EncryptedFieldPanel;
import org.apache.syncope.client.ui.commons.markup.html.form.FieldPanel;
-import org.apache.syncope.client.ui.commons.wicket.markup.html.bootstrap.tabs.Accordion;
-import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
-import org.apache.syncope.common.lib.EntityTOUtils;
-import org.apache.syncope.common.lib.SyncopeConstants;
-import org.apache.syncope.common.lib.to.AnyObjectTO;
import org.apache.syncope.common.lib.to.AnyTO;
-import org.apache.syncope.common.lib.Attr;
-import org.apache.syncope.common.lib.Attributable;
-import org.apache.syncope.common.lib.to.GroupTO;
import org.apache.syncope.common.lib.to.GroupableRelatableTO;
import org.apache.syncope.common.lib.to.MembershipTO;
import org.apache.syncope.common.lib.to.PlainSchemaTO;
-import org.apache.syncope.common.lib.to.UserTO;
-import org.apache.syncope.common.lib.types.AttrSchemaType;
-import org.apache.syncope.common.lib.types.SchemaType;
-import org.apache.wicket.PageReference;
-import org.apache.wicket.extensions.markup.html.tabs.AbstractTab;
-import org.apache.wicket.markup.html.WebMarkupContainer;
-import org.apache.wicket.markup.html.form.IChoiceRenderer;
-import org.apache.wicket.markup.html.list.ListItem;
-import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.LoadableDetachableModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.PropertyModel;
-import org.apache.wicket.model.ResourceModel;
import org.apache.wicket.model.StringResourceModel;
-import org.apache.wicket.model.util.ListModel;
public class PlainAttrs extends AbstractAttrs<PlainSchemaTO> {
private static final long serialVersionUID = 552437609667518888L;
- protected final AjaxWizard.Mode mode;
-
protected final AnyTO previousObject;
protected String fileKey = "";
- public <T extends AnyTO> PlainAttrs(
- final AnyWrapper<T> modelObject,
- final AjaxWizard.Mode mode,
+ public PlainAttrs(
+ final String id,
+ final UserWrapper modelObject,
final List<String> anyTypeClasses,
final Map<String, CustomizationOption> whichPlainAttrs) throws IllegalArgumentException {
- super(modelObject, anyTypeClasses, whichPlainAttrs);
- this.mode = mode;
+ super(id, modelObject, anyTypeClasses, whichPlainAttrs);
- if (modelObject.getInnerObject() instanceof UserTO) {
- fileKey = UserTO.class.cast(modelObject.getInnerObject()).getUsername();
- } else if (modelObject.getInnerObject() instanceof GroupTO) {
- fileKey = GroupTO.class.cast(modelObject.getInnerObject()).getName();
- } else if (modelObject.getInnerObject() instanceof AnyObjectTO) {
- fileKey = AnyObjectTO.class.cast(modelObject.getInnerObject()).getName();
- }
+ fileKey = modelObject.getInnerObject().getUsername();
- if (modelObject instanceof UserWrapper) {
- previousObject = UserWrapper.class.cast(modelObject).getPreviousUserTO();
- } else {
- previousObject = null;
- }
+ previousObject = modelObject.getPreviousUserTO();
- setTitleModel(new ResourceModel("attributes.plain"));
-
- add(new Accordion("plainSchemas", List.of(new AbstractTab(
- new ResourceModel("attributes.accordion", "Plain Attributes")) {
-
- private static final long serialVersionUID = 1037272333056449378L;
-
- @Override
- public WebMarkupContainer getPanel(final String panelId) {
- return new PlainSchemasOwn(panelId, schemas, attrs);
- }
- }), Model.of(0)).setOutputMarkupId(true));
-
+ add(new PlainSchemasOwn("plainSchemas", schemas, attrs).setOutputMarkupId(true));
add(new ListView<MembershipTO>("membershipsPlainSchemas", membershipTOs) {
- private static final long serialVersionUID = 1749643897846L;
+ private static final long serialVersionUID = 6741044372185745296L;
@Override
protected void populateItem(final ListItem<MembershipTO> item) {
final MembershipTO membershipTO = item.getModelObject();
- item.add(new Accordion("membershipPlainSchemas", List.of(new AbstractTab(
+ item.add(new Accordion("membershipPlainSchemas", Collections.<ITab>singletonList(new AbstractTab(
new StringResourceModel(
"attributes.membership.accordion",
PlainAttrs.this,
@@ -158,11 +131,6 @@
}
@Override
- protected boolean filterSchemas() {
- return super.filterSchemas() && mode != AjaxWizard.Mode.TEMPLATE;
- }
-
- @Override
protected List<Attr> getAttrsFromTO() {
return anyTO.getPlainAttrs().stream().sorted(attrComparator).collect(Collectors.toList());
}
@@ -174,11 +142,11 @@
@Override
protected void setAttrs() {
- List<Attr> attrs = new ArrayList<>();
+ List<Attr> plainAttrs = new ArrayList<>();
Map<String, Attr> attrMap = EntityTOUtils.buildAttrMap(anyTO.getPlainAttrs());
- attrs.addAll(schemas.values().stream().map(schema -> {
+ plainAttrs.addAll(schemas.values().stream().map(schema -> {
Attr attrTO = new Attr();
attrTO.setSchema(schema.getKey());
if (attrMap.get(schema.getKey()) == null || attrMap.get(schema.getKey()).getValues().isEmpty()) {
@@ -190,7 +158,7 @@
}).collect(Collectors.toList()));
anyTO.getPlainAttrs().clear();
- anyTO.getPlainAttrs().addAll(attrs);
+ anyTO.getPlainAttrs().addAll(plainAttrs);
}
@Override
@@ -205,17 +173,16 @@
attrMap = new HashMap<>();
}
- plainAttrs.addAll(membershipSchemas.get(membershipTO.getGroupKey()).values().stream().
- map(schema -> {
- Attr attrTO = new Attr();
- attrTO.setSchema(schema.getKey());
- if (attrMap.get(schema.getKey()) == null || attrMap.get(schema.getKey()).getValues().isEmpty()) {
- attrTO.getValues().add(StringUtils.EMPTY);
- } else {
- attrTO.getValues().addAll(attrMap.get(schema.getKey()).getValues());
- }
- return attrTO;
- }).collect(Collectors.toList()));
+ plainAttrs.addAll(membershipSchemas.get(membershipTO.getGroupKey()).values().stream().map(schema -> {
+ Attr attr = new Attr();
+ attr.setSchema(schema.getKey());
+ if (attrMap.get(schema.getKey()) == null || attrMap.get(schema.getKey()).getValues().isEmpty()) {
+ attr.getValues().add(StringUtils.EMPTY);
+ } else {
+ attr.getValues().addAll(attrMap.get(schema.getKey()).getValues());
+ }
+ return attr;
+ }).collect(Collectors.toList()));
membershipTO.getPlainAttrs().clear();
membershipTO.getPlainAttrs().addAll(plainAttrs);
@@ -238,7 +205,7 @@
case Boolean:
panel = new AjaxCheckBoxPanel(
"panel",
- schemaTO.getLabel(getLocale()),
+ schemaTO.getLabel(SyncopeEnduserSession.get().getLocale()),
new Model<>(),
true);
panel.setRequired(required);
@@ -252,13 +219,13 @@
if (datePattern.contains("H")) {
panel = new AjaxDateTimeFieldPanel(
"panel",
- schemaTO.getLabel(getLocale()),
+ schemaTO.getLabel(SyncopeEnduserSession.get().getLocale()),
new Model<>(),
FastDateFormat.getInstance(datePattern));
} else {
panel = new AjaxDateFieldPanel(
"panel",
- schemaTO.getLabel(getLocale()),
+ schemaTO.getLabel(SyncopeEnduserSession.get().getLocale()),
new Model<>(),
FastDateFormat.getInstance(datePattern));
}
@@ -271,7 +238,7 @@
case Enum:
panel = new AjaxDropDownChoicePanel<>("panel",
- schemaTO.getLabel(getLocale()), new Model<>(), true);
+ schemaTO.getLabel(SyncopeEnduserSession.get().getLocale()), new Model<>(), true);
((AjaxDropDownChoicePanel<String>) panel).setChoices(SchemaUtils.getEnumeratedValues(schemaTO));
if (StringUtils.isNotBlank(schemaTO.getEnumerationKeys())) {
@@ -307,7 +274,7 @@
case Long:
panel = new AjaxSpinnerFieldPanel.Builder<Long>().enableOnChange().build(
"panel",
- schemaTO.getLabel(getLocale()),
+ schemaTO.getLabel(SyncopeEnduserSession.get().getLocale()),
Long.class,
new Model<>());
@@ -319,7 +286,7 @@
case Double:
panel = new AjaxSpinnerFieldPanel.Builder<Double>().enableOnChange().step(0.1).build(
"panel",
- schemaTO.getLabel(getLocale()),
+ schemaTO.getLabel(SyncopeEnduserSession.get().getLocale()),
Double.class,
new Model<>());
@@ -329,22 +296,12 @@
break;
case Binary:
- final PageReference pageRef = getPageReference();
panel = new BinaryFieldPanel(
"panel",
- schemaTO.getLabel(getLocale()),
+ schemaTO.getLabel(SyncopeEnduserSession.get().getLocale()),
new Model<>(),
schemaTO.getMimeType(),
- fileKey) {
-
- private static final long serialVersionUID = -3268213909514986831L;
-
- @Override
- protected PageReference getPageReference() {
- return pageRef;
- }
-
- };
+ fileKey);
if (required) {
panel.addRequiredLabel();
}
@@ -352,7 +309,7 @@
case Encrypted:
panel = new EncryptedFieldPanel("panel",
- schemaTO.getLabel(getLocale()), new Model<>(), true);
+ schemaTO.getLabel(SyncopeEnduserSession.get().getLocale()), new Model<>(), true);
if (required) {
panel.addRequiredLabel();
@@ -361,7 +318,7 @@
default:
panel = new AjaxTextFieldPanel("panel",
- schemaTO.getLabel(getLocale()), new Model<>(), true);
+ schemaTO.getLabel(SyncopeEnduserSession.get().getLocale()), new Model<>(), true);
if (jexlHelp) {
AjaxTextFieldPanel.class.cast(panel).enableJexlHelp();
@@ -375,6 +332,10 @@
panel.setReadOnly(readOnly);
panel.setMarkupId(StringUtils.isBlank(groupName) ? schemaTO.getKey() : groupName + '.' + schemaTO.getKey());
+ Label label = (Label) panel.get(AbstractFieldPanel.LABEL);
+ label.add(new AttributeModifier("for", FORM_SUFFIX
+ + (StringUtils.isBlank(groupName) ? schemaTO.getKey() : groupName + '.' + schemaTO.getKey())));
+
return panel;
}
@@ -400,25 +361,25 @@
@Override
@SuppressWarnings({ "unchecked", "rawtypes" })
protected void populateItem(final ListItem<Attr> item) {
- Attr attr = item.getModelObject();
- PlainSchemaTO schema = schemas.get(attr.getSchema());
+ Attr attrTO = item.getModelObject();
+ PlainSchemaTO schema = schemas.get(attrTO.getSchema());
// set default values, if any
- if (attr.getValues().stream().noneMatch(StringUtils::isNotBlank)) {
- attr.getValues().clear();
- attr.getValues().addAll(getDefaultValues(attr.getSchema(), groupName));
+ if (attrTO.getValues().stream().noneMatch(StringUtils::isNotBlank)) {
+ attrTO.getValues().clear();
+ attrTO.getValues().addAll(getDefaultValues(attrTO.getSchema(), groupName));
}
- AbstractFieldPanel<?> panel = getFieldPanel(schemas.get(attr.getSchema()));
- if (schemas.get(attr.getSchema()).isMultivalue()) {
+ AbstractFieldPanel<?> panel = getFieldPanel(schemas.get(attrTO.getSchema()));
+ if (schemas.get(attrTO.getSchema()).isMultivalue()) {
panel = new MultiFieldPanel.Builder<>(
new PropertyModel<>(
- attributableTO.getObject().getPlainAttr(attr.getSchema()), "values"))
- .build("panel", attr.getSchema(), FieldPanel.class.cast(panel));
+ attributableTO.getObject().getPlainAttr(attrTO.getSchema()), "values"))
+ .build("panel", attrTO.getSchema(), FieldPanel.class.cast(panel));
// SYNCOPE-1215 the entire multifield panel must be readonly, not only its field
((MultiFieldPanel) panel).setReadOnly(schema == null ? false : schema.isReadonly());
} else {
- FieldPanel.class.cast(panel).setNewModel(attr.getValues()).
+ FieldPanel.class.cast(panel).setNewModel(attrTO.getValues()).
setReadOnly(schema == null ? false : schema.isReadonly());
}
@@ -446,26 +407,26 @@
@Override
@SuppressWarnings({ "unchecked", "rawtypes" })
protected void populateItem(final ListItem<Attr> item) {
- Attr attr = item.getModelObject();
- PlainSchemaTO schema = schemas.get(attr.getSchema());
+ Attr attrTO = item.getModelObject();
+ PlainSchemaTO schema = schemas.get(attrTO.getSchema());
// set default values, if any
- if (attr.getValues().stream().noneMatch(StringUtils::isNotBlank)) {
- attr.getValues().clear();
- attr.getValues().addAll(getDefaultValues(attr.getSchema()));
+ if (attrTO.getValues().stream().noneMatch(StringUtils::isNotBlank)) {
+ attrTO.getValues().clear();
+ attrTO.getValues().addAll(getDefaultValues(attrTO.getSchema()));
}
- AbstractFieldPanel<?> panel = getFieldPanel(schemas.get(attr.getSchema()));
- if (schemas.get(attr.getSchema()).isMultivalue()) {
+ AbstractFieldPanel<?> panel = getFieldPanel(schemas.get(attrTO.getSchema()));
+ if (schemas.get(attrTO.getSchema()).isMultivalue()) {
panel = new MultiFieldPanel.Builder<>(
- new PropertyModel<>(attr, "values")).build(
+ new PropertyModel<>(attrTO, "values")).build(
"panel",
- attr.getSchema(),
+ attrTO.getSchema(),
FieldPanel.class.cast(panel));
// SYNCOPE-1215 the entire multifield panel must be readonly, not only its field
((MultiFieldPanel) panel).setReadOnly(schema == null ? false : schema.isReadonly());
} else {
- FieldPanel.class.cast(panel).setNewModel(attr.getValues()).
+ FieldPanel.class.cast(panel).setNewModel(attrTO.getValues()).
setReadOnly(schema == null ? false : schema.isReadonly());
}
item.add(panel);
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/any/Resources.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/any/Resources.java
new file mode 100644
index 0000000..93265e8
--- /dev/null
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/any/Resources.java
@@ -0,0 +1,87 @@
+/*
+ * 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.enduser.panels.any;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.enduser.SyncopeEnduserSession;
+import org.apache.syncope.client.ui.commons.ajax.markup.html.LabelInfo;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxPalettePanel;
+import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
+import org.apache.syncope.client.ui.commons.wizards.any.UserWrapper;
+import org.apache.syncope.common.lib.to.AnyTO;
+import org.apache.syncope.common.rest.api.service.SyncopeService;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.PropertyModel;
+import org.apache.wicket.model.util.ListModel;
+
+public class Resources extends Panel {
+
+ private static final long serialVersionUID = 702900610508752856L;
+
+ protected final ListModel<String> available;
+
+ public <T extends AnyTO> Resources(final String id, final AnyWrapper<T> modelObject) {
+ super(id);
+ final T entityTO = modelObject.getInnerObject();
+
+ if (modelObject instanceof UserWrapper
+ && UserWrapper.class.cast(modelObject).getPreviousUserTO() != null
+ && !modelObject.getInnerObject().getResources().equals(
+ UserWrapper.class.cast(modelObject).getPreviousUserTO().getResources())) {
+
+ add(new LabelInfo("changed", StringUtils.EMPTY));
+ } else {
+ add(new Label("changed", StringUtils.EMPTY));
+ }
+
+ this.setOutputMarkupId(true);
+ this.available = new ListModel<>(List.of());
+
+ add(new AjaxPalettePanel.Builder<String>().build("resources",
+ new PropertyModel<List<String>>(entityTO, "resources") {
+
+ private static final long serialVersionUID = 3799387950428254072L;
+
+ @Override
+ public List<String> getObject() {
+ return new ArrayList<>(entityTO.getResources());
+ }
+
+ @Override
+ public void setObject(final List<String> object) {
+ entityTO.getResources().clear();
+ entityTO.getResources().addAll(object);
+ }
+ }, available).hideLabel().setOutputMarkupId(true));
+ }
+
+ @Override
+ protected void onInitialize() {
+ super.onInitialize();
+ available.setObject(SyncopeEnduserSession.get().getService(SyncopeService.class).platform().getResources());
+ }
+
+ public boolean evaluate() {
+ available.setObject(SyncopeEnduserSession.get().getService(SyncopeService.class).platform().getResources());
+ return !available.getObject().isEmpty();
+ }
+}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/any/SelfUserDetails.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/any/SelfUserDetails.java
new file mode 100644
index 0000000..3918934
--- /dev/null
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/any/SelfUserDetails.java
@@ -0,0 +1,46 @@
+/*
+ * 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.enduser.panels.any;
+
+import org.apache.syncope.client.ui.commons.wizards.any.UserWrapper;
+import org.apache.wicket.PageReference;
+
+public class SelfUserDetails extends UserDetails {
+
+ private static final long serialVersionUID = 6592027822510220469L;
+
+ public SelfUserDetails(
+ final String id,
+ final UserWrapper wrapper,
+ final boolean templateMode,
+ final boolean includeStatusPanel,
+ final boolean showPasswordManagement,
+ final PageReference pageRef) {
+
+ super(id, wrapper, templateMode, includeStatusPanel, pageRef);
+
+ // ------------------------
+ // Password
+ // ------------------------
+ EditUserPasswordPanel panel = new EditUserPasswordPanel("password", wrapper, templateMode);
+ panel.setVisible(showPasswordManagement);
+
+ add(panel);
+ }
+}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/any/UserDetails.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/any/UserDetails.java
new file mode 100644
index 0000000..8897db7
--- /dev/null
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/any/UserDetails.java
@@ -0,0 +1,113 @@
+/*
+ * 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.enduser.panels.any;
+
+import de.agilecoders.wicket.extensions.markup.html.bootstrap.form.password.strength.PasswordStrengthBehavior;
+import de.agilecoders.wicket.extensions.markup.html.bootstrap.form.password.strength.PasswordStrengthConfig;
+import java.util.stream.Collectors;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.enduser.rest.RealmRestClient;
+import org.apache.syncope.client.ui.commons.ajax.markup.html.LabelInfo;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.FieldPanel;
+import org.apache.syncope.client.ui.commons.wizards.any.PasswordPanel;
+import org.apache.syncope.client.ui.commons.wizards.any.UserWrapper;
+import org.apache.syncope.common.lib.to.RealmTO;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.PropertyModel;
+import org.apache.wicket.model.ResourceModel;
+
+public class UserDetails extends Details<UserTO> {
+
+ private static final long serialVersionUID = 6592027822510220463L;
+
+ private final FieldPanel<String> realm;
+
+ protected final AjaxTextFieldPanel username;
+
+ protected final UserTO userTO;
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ public UserDetails(
+ final String id,
+ final UserWrapper wrapper,
+ final boolean templateMode,
+ final boolean includeStatusPanel,
+ final PageReference pageRef) {
+
+ super(id, wrapper, templateMode, includeStatusPanel, pageRef);
+
+ userTO = wrapper.getInnerObject();
+ // ------------------------
+ // Username
+ // ------------------------
+ username = new AjaxTextFieldPanel("username", "username", new PropertyModel<>(userTO, "username"), false);
+
+ if (wrapper.getPreviousUserTO() != null && StringUtils.
+ compare(wrapper.getPreviousUserTO().getUsername(), wrapper.getInnerObject().getUsername()) != 0) {
+ username.showExternAction(new LabelInfo("externalAction", wrapper.getPreviousUserTO().getUsername()));
+ }
+
+ if (templateMode) {
+ username.enableJexlHelp();
+ } else {
+ username.addRequiredLabel();
+ }
+ add(username);
+ // ------------------------
+
+ // ------------------------
+ // Realm
+ // ------------------------
+ realm = new AjaxDropDownChoicePanel<>(
+ "destinationRealm", "destinationRealm", new PropertyModel<>(userTO, "realm"), false);
+
+ ((AjaxDropDownChoicePanel<String>) realm).setChoices(
+ RealmRestClient.list().stream().map(RealmTO::getFullPath).collect(Collectors.toList()));
+ add(realm);
+ }
+
+ protected static class EditUserPasswordPanel extends Panel {
+
+ private static final long serialVersionUID = -8198836979773590078L;
+
+ protected EditUserPasswordPanel(
+ final String id,
+ final UserWrapper wrapper,
+ final boolean templateMode) {
+
+ super(id);
+ setOutputMarkupId(true);
+ add(new Label("warning", new ResourceModel("password.change.warning")));
+ add(new PasswordPanel(
+ "passwordPanel",
+ wrapper,
+ templateMode,
+ wrapper.getInnerObject().getKey() == null,
+ new PasswordStrengthBehavior(new PasswordStrengthConfig().
+ withDebug(false).
+ withShowVerdictsInsideProgressBar(true).
+ withShowProgressBar(true))));
+ }
+ }
+}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/VirAttrs.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/any/VirAttrs.java
similarity index 82%
rename from client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/VirAttrs.java
rename to client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/any/VirAttrs.java
index 86c55b2..65386d9 100644
--- a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/VirAttrs.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/any/VirAttrs.java
@@ -16,86 +16,77 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.syncope.client.enduser.wizards.any;
+package org.apache.syncope.client.enduser.panels.any;
-import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
import org.apache.syncope.client.enduser.SyncopeEnduserSession;
import org.apache.syncope.client.enduser.layout.CustomizationOption;
import org.apache.syncope.client.enduser.markup.html.form.MultiFieldPanel;
-import org.apache.syncope.client.ui.commons.wicket.markup.html.bootstrap.tabs.Accordion;
import org.apache.syncope.client.ui.commons.markup.html.form.AbstractFieldPanel;
import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.ui.commons.wicket.markup.html.bootstrap.tabs.Accordion;
+import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
+import org.apache.syncope.common.lib.Attr;
import org.apache.syncope.common.lib.EntityTOUtils;
import org.apache.syncope.common.lib.to.AnyTO;
-import org.apache.syncope.common.lib.Attr;
import org.apache.syncope.common.lib.to.GroupableRelatableTO;
import org.apache.syncope.common.lib.to.MembershipTO;
import org.apache.syncope.common.lib.to.VirSchemaTO;
import org.apache.syncope.common.lib.types.SchemaType;
import org.apache.wicket.extensions.markup.html.tabs.AbstractTab;
+import org.apache.wicket.extensions.markup.html.tabs.ITab;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.PropertyModel;
-import org.apache.wicket.model.ResourceModel;
import org.apache.wicket.model.StringResourceModel;
import org.apache.wicket.model.util.ListModel;
+import java.util.stream.Collectors;
public class VirAttrs extends AbstractAttrs<VirSchemaTO> {
private static final long serialVersionUID = -7982691107029848579L;
public <T extends AnyTO> VirAttrs(
+ final String id,
final AnyWrapper<T> modelObject,
final List<String> anyTypeClasses,
final Map<String, CustomizationOption> whichVirAttrs) {
- super(modelObject, anyTypeClasses, whichVirAttrs);
+ super(id, modelObject, anyTypeClasses, whichVirAttrs);
- setTitleModel(new ResourceModel("attributes.virtual"));
-
- add(new Accordion("virSchemas", List.of(new AbstractTab(
- new ResourceModel("attributes.accordion", "Virtual Attributes")) {
-
- private static final long serialVersionUID = 1037272333056449378L;
-
- @Override
- public WebMarkupContainer getPanel(final String panelId) {
- return new VirAttrs.VirSchemas(panelId, schemas, attrs);
- }
- }), Model.of(0)).setOutputMarkupId(true));
-
+ add(new VirAttrs.VirSchemas("virSchemas", schemas, attrs).setOutputMarkupId(true));
add(new ListView<MembershipTO>("membershipsVirSchemas", membershipTOs) {
private static final long serialVersionUID = 9101744072914090143L;
@Override
protected void populateItem(final ListItem<MembershipTO> item) {
- MembershipTO membTO = item.getModelObject();
- item.add(new Accordion("membershipVirSchemas", List.of(new AbstractTab(
- new StringResourceModel("attributes.membership.accordion", VirAttrs.this, Model.of(membTO))) {
+ 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))) {
- private static final long serialVersionUID = 1037272333056449378L;
+ private static final long serialVersionUID = 1037272333056449378L;
- @Override
- public WebMarkupContainer getPanel(final String panelId) {
- return new VirAttrs.VirSchemas(
- panelId,
- membTO.getGroupName(),
- membershipSchemas.get(membTO.getGroupKey()),
- new ListModel<>(getAttrsFromTO(membTO)));
- }
- }), Model.of(-1)).setOutputMarkupId(true));
+ @Override
+ public WebMarkupContainer getPanel(final String panelId) {
+ return new VirAttrs.VirSchemas(
+ panelId,
+ membershipTO.getGroupName(),
+ membershipSchemas.get(membershipTO.getGroupKey()),
+ new ListModel<>(getAttrsFromTO(membershipTO)));
+ }
+ }), Model.of(-1)).setOutputMarkupId(true));
}
- });
+ }).setOutputMarkupId(true);
}
@Override
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/CaptchaPanel.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/captcha/CaptchaPanel.java
similarity index 83%
rename from client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/CaptchaPanel.java
rename to client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/captcha/CaptchaPanel.java
index 4b886bf..007e26b 100644
--- a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/CaptchaPanel.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/captcha/CaptchaPanel.java
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.syncope.client.enduser.wizards.any;
+package org.apache.syncope.client.enduser.panels.captcha;
import java.security.SecureRandom;
import org.apache.commons.lang3.StringUtils;
@@ -31,7 +31,7 @@
public class CaptchaPanel<T> extends Panel {
- private static final long serialVersionUID = 1169850573252481471L;
+ private static final long serialVersionUID = -450657681453274465L;
private static final SecureRandom RANDOM = new SecureRandom();
@@ -40,8 +40,6 @@
withinRange('a', 'z').
build();
- private String randomText;
-
private final Model<String> captchaText = new Model<>();
private final CaptchaImageResource captchaImageResource;
@@ -55,8 +53,7 @@
@Override
protected byte[] render() {
- randomText = RANDOM_LETTERS.generate(6);
- getChallengeIdModel().setObject(randomText);
+ getChallengeIdModel().setObject(RANDOM_LETTERS.generate(6));
return super.render();
}
};
@@ -82,13 +79,13 @@
setOutputMarkupPlaceholderTag(true));
}
- public void reload() {
- this.captchaImageResource.invalidate();
- }
-
- public boolean captchaCheck() {
- return StringUtils.isBlank(captchaText.getObject()) || StringUtils.isBlank(randomText)
+ public boolean check() {
+ boolean check = StringUtils.isBlank(captchaText.getObject())
+ || StringUtils.isBlank(captchaImageResource.getChallengeId())
? false
- : captchaText.getObject().equals(randomText);
+ : captchaText.getObject().equals(captchaImageResource.getChallengeId());
+
+ captchaImageResource.invalidate();
+ return check;
}
}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/resources/CaptchaResource.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/resources/CaptchaResource.java
deleted file mode 100644
index 7cbb5f5..0000000
--- a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/resources/CaptchaResource.java
+++ /dev/null
@@ -1,56 +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.enduser.resources;
-
-import java.security.SecureRandom;
-import javax.servlet.http.HttpServletRequest;
-import org.apache.commons.text.RandomStringGenerator;
-import org.apache.syncope.client.enduser.SyncopeEnduserConstants;
-import org.apache.wicket.extensions.markup.html.captcha.CaptchaImageResource;
-import org.apache.wicket.request.cycle.RequestCycle;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class CaptchaResource extends CaptchaImageResource {
-
- private static final long serialVersionUID = 8293404296348102926L;
-
- private static final SecureRandom RANDOM = new SecureRandom();
-
- private static final Logger LOG = LoggerFactory.getLogger(CaptchaResource.class);
-
- private static final RandomStringGenerator RANDOM_LETTERS = new RandomStringGenerator.Builder().
- usingRandom(RANDOM::nextInt).
- withinRange('a', 'z').
- build();
-
- @Override
- protected byte[] render() {
- LOG.debug("Generate captcha");
-
- String captcha = RANDOM_LETTERS.generate(6);
- HttpServletRequest request = ((HttpServletRequest) RequestCycle.get().getRequest().getContainerRequest());
- // store the captcha in the current session
- request.getSession().setAttribute(SyncopeEnduserConstants.CAPTCHA_SESSION_KEY, captcha);
-
- getChallengeIdModel().setObject(captcha);
- return super.render();
- }
-
-}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/rest/AnyTypeRestClient.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/rest/AnyTypeRestClient.java
index 8f3c823..09c6ea9 100644
--- a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/rest/AnyTypeRestClient.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/rest/AnyTypeRestClient.java
@@ -19,6 +19,7 @@
package org.apache.syncope.client.enduser.rest;
import java.io.Serializable;
+import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import org.apache.commons.lang3.ObjectUtils;
@@ -47,7 +48,7 @@
}
public static List<AnyTypeTO> listAnyTypes() {
- List<AnyTypeTO> types = List.of();
+ List<AnyTypeTO> types = Collections.emptyList();
try {
types = getService(AnyTypeService.class).list();
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/rest/BaseRestClient.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/rest/BaseRestClient.java
index 6f9e4ff..97196c0 100644
--- a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/rest/BaseRestClient.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/rest/BaseRestClient.java
@@ -18,10 +18,17 @@
*/
package org.apache.syncope.client.enduser.rest;
+import java.net.URI;
+import javax.ws.rs.core.HttpHeaders;
+import org.apache.cxf.jaxrs.client.WebClient;
import org.apache.syncope.client.enduser.SyncopeEnduserSession;
import org.apache.syncope.client.lib.SyncopeClient;
+import org.apache.syncope.client.ui.commons.Constants;
import org.apache.syncope.client.ui.commons.rest.RestClient;
import org.apache.syncope.common.lib.search.OrderByClauseBuilder;
+import org.apache.syncope.common.lib.types.ExecStatus;
+import org.apache.syncope.common.rest.api.RESTHeaders;
+import org.apache.syncope.common.rest.api.service.JAXRSService;
import org.apache.syncope.common.rest.api.service.SyncopeService;
import org.apache.wicket.extensions.markup.html.repeater.util.SortParam;
import org.slf4j.Logger;
@@ -49,7 +56,7 @@
SyncopeEnduserSession.get().resetClient(serviceClass);
}
- protected static String toOrderBy(final SortParam<String> sort) {
+ public static String toOrderBy(final SortParam<String> sort) {
OrderByClauseBuilder builder = SyncopeClient.getOrderByClauseBuilder();
String property = sort.getProperty();
@@ -65,4 +72,22 @@
return builder.build();
}
+
+ protected static <E extends JAXRSService, T> T getObject(
+ final E service, final URI location, final Class<T> resultClass) {
+
+ WebClient webClient = WebClient.fromClient(WebClient.client(service));
+ webClient.accept(SyncopeEnduserSession.get().getMediaType()).to(location.toASCIIString(), false);
+ return webClient.
+ header(RESTHeaders.DOMAIN, SyncopeEnduserSession.get().getDomain()).
+ header(HttpHeaders.AUTHORIZATION, "Bearer " + SyncopeEnduserSession.get().getJWT()).
+ get(resultClass);
+ }
+
+ protected static String getStatus(final int httpStatus) {
+ ExecStatus execStatus = ExecStatus.fromHttpStatus(httpStatus);
+ return execStatus == null
+ ? Constants.UNKNOWN
+ : execStatus.name();
+ }
}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/rest/GroupRestClient.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/rest/GroupRestClient.java
index f9e22c3..23c98fd 100644
--- a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/rest/GroupRestClient.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/rest/GroupRestClient.java
@@ -18,9 +18,8 @@
*/
package org.apache.syncope.client.enduser.rest;
-import java.util.List;
-import javax.ws.rs.core.GenericType;
-import javax.ws.rs.core.Response;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.common.lib.SyncopeConstants;
import org.apache.syncope.common.lib.request.GroupCR;
import org.apache.syncope.common.lib.request.GroupUR;
import org.apache.syncope.common.lib.to.GroupTO;
@@ -29,6 +28,9 @@
import org.apache.syncope.common.rest.api.service.AnyService;
import org.apache.syncope.common.rest.api.service.GroupService;
import org.apache.syncope.common.rest.api.service.SyncopeService;
+import javax.ws.rs.core.GenericType;
+import javax.ws.rs.core.Response;
+import java.util.List;
/**
* Console client for invoking Rest Group's services.
@@ -42,16 +44,16 @@
return GroupService.class;
}
- public static ProvisioningResult<GroupTO> create(final GroupCR groupCR) {
- Response response = getService(GroupService.class).create(groupCR);
+ public static ProvisioningResult<GroupTO> create(final GroupCR groupTO) {
+ Response response = getService(GroupService.class).create(groupTO);
return response.readEntity(new GenericType<ProvisioningResult<GroupTO>>() {
});
}
- public ProvisioningResult<GroupTO> update(final String etag, final GroupUR updateReq) {
+ public ProvisioningResult<GroupTO> update(final String etag, final GroupUR groupPatch) {
ProvisioningResult<GroupTO> result;
synchronized (this) {
- result = getService(etag, GroupService.class).update(updateReq).
+ result = getService(etag, GroupService.class).update(groupPatch).
readEntity(new GenericType<ProvisioningResult<GroupTO>>() {
});
resetClient(getAnyServiceClass());
@@ -65,7 +67,8 @@
final int page,
final int size) {
- return getService(SyncopeService.class).searchAssignableGroups(realm, term, page, size).getResult();
+ return getService(SyncopeService.class).searchAssignableGroups(
+ StringUtils.isNotEmpty(realm) ? realm : SyncopeConstants.ROOT_REALM, term, page, size).getResult();
}
@Override
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/rest/RoleRestClient.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/rest/RoleRestClient.java
deleted file mode 100644
index 6b3aea3..0000000
--- a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/rest/RoleRestClient.java
+++ /dev/null
@@ -1,80 +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.enduser.rest;
-
-import java.io.InputStream;
-import java.nio.charset.StandardCharsets;
-import java.util.List;
-import java.util.stream.Collectors;
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.syncope.common.lib.to.RoleTO;
-import org.apache.syncope.common.rest.api.service.RoleService;
-
-/**
- * Console client for invoking Rest Role's services.
- */
-public class RoleRestClient extends BaseRestClient {
-
- private static final long serialVersionUID = -3161863874876938094L;
-
- public static void delete(final String key) {
- getService(RoleService.class).delete(key);
- }
-
- public static RoleTO read(final String key) {
- return getService(RoleService.class).read(key);
- }
-
- public static void update(final RoleTO roleTO) {
- getService(RoleService.class).update(roleTO);
- }
-
- public static void create(final RoleTO roleTO) {
- getService(RoleService.class).create(roleTO);
- }
-
- public static List<RoleTO> list() {
- return getService(RoleService.class).list();
- }
-
- public static String readAnyLayout(final String roleKey) {
- try {
- return IOUtils.toString(InputStream.class.cast(
- getService(RoleService.class).getAnyLayout(roleKey).getEntity()),
- StandardCharsets.UTF_8);
- } catch (Exception e) {
- LOG.error("Error retrieving console layout info for role {}", roleKey, e);
- return StringUtils.EMPTY;
- }
- }
-
- public static void setAnyLayout(final String roleKey, final String content) {
- getService(RoleService.class).setAnyLayout(
- roleKey, IOUtils.toInputStream(content, StandardCharsets.UTF_8));
- }
-
- public static void removeAnyLayout(final String roleKey) {
- getService(RoleService.class).removeAnyLayout(roleKey);
- }
-
- public static List<String> getAllAvailableEntitlements() {
- return getSyncopeService().platform().getEntitlements().stream().sorted().collect(Collectors.toList());
- }
-}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/rest/SchemaRestClient.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/rest/SchemaRestClient.java
index c89e35b..666b273 100644
--- a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/rest/SchemaRestClient.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/rest/SchemaRestClient.java
@@ -19,6 +19,7 @@
package org.apache.syncope.client.enduser.rest;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
@@ -86,7 +87,7 @@
}
public static List<String> getSchemaNames(final SchemaType schemaType) {
- List<String> schemaNames = List.of();
+ List<String> schemaNames = Collections.emptyList();
try {
schemaNames = getSchemas(schemaType, null, new String[0]).stream().
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/rest/SyncopeRestClient.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/rest/SyncopeRestClient.java
index 74429c8..233dd51 100644
--- a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/rest/SyncopeRestClient.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/rest/SyncopeRestClient.java
@@ -18,6 +18,7 @@
*/
package org.apache.syncope.client.enduser.rest;
+import java.util.Collections;
import java.util.List;
import org.apache.syncope.common.lib.SyncopeClientException;
import org.apache.syncope.common.lib.to.TypeExtensionTO;
@@ -28,7 +29,7 @@
private static final long serialVersionUID = -2211371717449597247L;
public static List<String> listAnyTypeClasses() {
- List<String> types = List.of();
+ List<String> types = Collections.emptyList();
try {
types = getService(SyncopeService.class).platform().getAnyTypeClasses();
@@ -39,13 +40,14 @@
}
public static List<String> searchUserTypeExtensions(final String groupName) {
- List<String> types = List.of();
+ List<String> types = Collections.emptyList();
try {
TypeExtensionTO typeExtensionTO = getService(SyncopeService.class).readUserTypeExtension(groupName);
types = typeExtensionTO == null ? types : typeExtensionTO.getAuxClasses();
- } catch (SyncopeClientException e) {
+ } catch (Exception e) {
LOG.error("While reading all any type classes for group [{}]", groupName, e);
}
return types;
}
+
}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/rest/UserSelfRestClient.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/rest/UserSelfRestClient.java
index 95a35ce..f7cf9cf 100644
--- a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/rest/UserSelfRestClient.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/rest/UserSelfRestClient.java
@@ -18,46 +18,17 @@
*/
package org.apache.syncope.client.enduser.rest;
-import javax.ws.rs.core.GenericType;
-import javax.ws.rs.core.Response;
-import org.apache.syncope.common.lib.request.BooleanReplacePatchItem;
import org.apache.syncope.common.lib.request.UserCR;
import org.apache.syncope.common.lib.request.UserUR;
import org.apache.syncope.common.lib.to.ProvisioningResult;
import org.apache.syncope.common.lib.to.UserTO;
import org.apache.syncope.common.rest.api.service.UserSelfService;
+import javax.ws.rs.core.GenericType;
-/**
- * Console client for invoking rest users services.
- */
public class UserSelfRestClient extends BaseRestClient {
private static final long serialVersionUID = -1575748964398293968L;
- public static ProvisioningResult<UserTO> create(final UserCR createReq) {
- Response response = getService(UserSelfService.class).create(createReq);
- return response.readEntity(new GenericType<ProvisioningResult<UserTO>>() {
- });
- }
-
- public ProvisioningResult<UserTO> update(final String etag, final UserUR updateReq) {
- ProvisioningResult<UserTO> result;
- synchronized (this) {
- result = getService(etag, UserSelfService.class).update(updateReq).
- readEntity(new GenericType<ProvisioningResult<UserTO>>() {
- });
- resetClient(UserSelfService.class);
- }
- return result;
- }
-
- public ProvisioningResult<UserTO> mustChangePassword(final String etag, final boolean value, final String key) {
- UserUR userUR = new UserUR();
- userUR.setKey(key);
- userUR.setMustChangePassword(new BooleanReplacePatchItem.Builder().value(value).build());
- return update(etag, userUR);
- }
-
public static void changePassword(final String password) {
getService(UserSelfService.class).mustChangePassword(password);
}
@@ -65,4 +36,23 @@
public static void requestPasswordReset(final String username, final String securityAnswer) {
getService(UserSelfService.class).requestPasswordReset(username, securityAnswer);
}
+
+ public ProvisioningResult<UserTO> create(final UserCR createReq, final boolean storePassword) {
+ ProvisioningResult<UserTO> result;
+ result = getService(UserSelfService.class).create(createReq).readEntity(
+ new GenericType<ProvisioningResult<UserTO>>() {
+ });
+ return result;
+ }
+
+ public ProvisioningResult<UserTO> update(final String etag, final UserUR userPatch) {
+ ProvisioningResult<UserTO> result;
+ synchronized (this) {
+ result = getService(etag, UserSelfService.class).update(userPatch).
+ readEntity(new GenericType<ProvisioningResult<UserTO>>() {
+ });
+ resetClient(UserSelfService.class);
+ }
+ return result;
+ }
}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wicket/markup/head/MetaHeaderItem.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wicket/markup/head/MetaHeaderItem.java
new file mode 100644
index 0000000..90ccf60
--- /dev/null
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wicket/markup/head/MetaHeaderItem.java
@@ -0,0 +1,49 @@
+/*
+ * 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.enduser.wicket.markup.head;
+
+import java.io.Serializable;
+import java.util.Arrays;
+import org.apache.wicket.markup.head.HeaderItem;
+import org.apache.wicket.request.Response;
+
+public class MetaHeaderItem extends HeaderItem implements Serializable {
+
+ private static final long serialVersionUID = 7578609827530302053L;
+
+ private final String key;
+
+ private final String value;
+
+ public MetaHeaderItem(final String key, final String value) {
+ this.key = key;
+ this.value = value;
+ }
+
+ @Override
+ public Iterable<?> getRenderTokens() {
+ return Arrays.asList("meta-" + key + "-" + value);
+ }
+
+ @Override
+ public void render(final Response response) {
+ response.write("<meta http-equiv=\"" + key + "\" content=\"" + value + "\"/>");
+ response.write("\n");
+ }
+}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/SelfUpdate.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/widgets/BaseWidget.java
similarity index 71%
rename from client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/SelfUpdate.java
rename to client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/widgets/BaseWidget.java
index 7c86c2d..8426ae5 100644
--- a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/SelfUpdate.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/widgets/BaseWidget.java
@@ -16,16 +16,16 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.syncope.client.enduser.pages;
+package org.apache.syncope.client.enduser.widgets;
-import org.apache.wicket.request.mapper.parameter.PageParameters;
+import org.apache.wicket.markup.html.panel.Panel;
-public class SelfUpdate extends BaseEnduserWebPage {
+public abstract class BaseWidget extends Panel {
- private static final long serialVersionUID = 164651008547631054L;
+ private static final long serialVersionUID = -4186604985011430091L;
- public SelfUpdate(final PageParameters parameters) {
- super(parameters);
+ public BaseWidget(final String id) {
+ super(id);
}
}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/widgets/UserProfileWidget.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/widgets/UserProfileWidget.java
new file mode 100644
index 0000000..9f52674
--- /dev/null
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/widgets/UserProfileWidget.java
@@ -0,0 +1,65 @@
+/*
+ * 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.enduser.widgets;
+
+import org.apache.syncope.client.enduser.SyncopeEnduserSession;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.basic.Label;
+
+public class UserProfileWidget extends BaseWidget {
+
+ private static final long serialVersionUID = 4437711189800676363L;
+
+ protected UserTO userTO;
+
+ public UserProfileWidget(final String id) {
+ super(id);
+
+ userTO = SyncopeEnduserSession.get().getSelfTO(true);
+
+ WebMarkupContainer userProfile = new WebMarkupContainer("userProfile");
+ userProfile.setOutputMarkupId(true);
+ add(userProfile);
+
+ Label welcome = new Label("welcome", userTO.getUsername());
+ welcome.setOutputMarkupId(true);
+ userProfile.add(welcome);
+
+ addBaseFields(userProfile);
+ addExtFields(userProfile);
+ }
+
+ protected void addBaseFields(final WebMarkupContainer userProfile) {
+ Label username = new Label("username", userTO.getUsername());
+ username.setOutputMarkupId(true);
+ userProfile.add(username);
+
+ Label changePwdDate = new Label("changePwdDate", userTO.getChangePwdDate());
+ changePwdDate.setOutputMarkupId(true);
+ userProfile.add(changePwdDate);
+
+ Label lastLoginDate = new Label("lastLoginDate", userTO.getLastLoginDate());
+ lastLoginDate.setOutputMarkupId(true);
+ userProfile.add(lastLoginDate);
+ }
+
+ protected void addExtFields(final WebMarkupContainer userProfile) {
+ }
+}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/AnyWizardBuilder.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/AnyWizardBuilder.java
deleted file mode 100644
index 922554e..0000000
--- a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/AnyWizardBuilder.java
+++ /dev/null
@@ -1,293 +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.enduser.wizards.any;
-
-import java.io.Serializable;
-import java.util.List;
-import java.util.concurrent.Callable;
-import java.util.concurrent.Future;
-import org.apache.commons.lang3.tuple.Pair;
-import org.apache.syncope.client.enduser.SyncopeWebApplication;
-import org.apache.syncope.client.enduser.SyncopeEnduserSession;
-import org.apache.syncope.client.enduser.layout.UserFormLayoutInfo;
-import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
-import org.apache.syncope.client.ui.commons.wizards.AjaxWizardMgtButtonBar;
-import org.apache.syncope.client.ui.commons.wizards.any.AbstractAnyWizardBuilder;
-import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
-import org.apache.syncope.client.ui.commons.wizards.any.UserWrapper;
-import org.apache.syncope.common.lib.to.UserTO;
-import org.apache.wicket.Component;
-import org.apache.wicket.PageReference;
-import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.extensions.wizard.FinishButton;
-import org.apache.wicket.extensions.wizard.IWizard;
-import org.apache.wicket.extensions.wizard.IWizardModel;
-import org.apache.wicket.extensions.wizard.IWizardStep;
-import org.apache.wicket.extensions.wizard.WizardModel;
-
-public abstract class AnyWizardBuilder extends AbstractAnyWizardBuilder<UserTO> {
-
- private static final long serialVersionUID = -2480279868319546243L;
-
- protected final List<String> anyTypeClasses;
-
- protected UserFormLayoutInfo formLayoutInfo;
-
- protected Captcha captcha;
-
- /**
- * Construct.
- *
- * @param anyTO any
- * @param anyTypeClasses any type classes
- * @param formLayoutInfo form layout info
- * @param pageRef caller page reference.
- */
- public AnyWizardBuilder(
- final UserTO anyTO,
- final List<String> anyTypeClasses,
- final UserFormLayoutInfo formLayoutInfo,
- final PageReference pageRef) {
-
- super(new AnyWrapper<>(anyTO), pageRef);
- this.anyTypeClasses = anyTypeClasses;
- this.formLayoutInfo = formLayoutInfo;
- }
-
- /**
- * Construct.
- *
- * @param wrapper any wrapper
- * @param anyTypeClasses any type classes
- * @param formLayoutInfo form layout info
- * @param pageRef caller page reference.
- */
- public AnyWizardBuilder(
- final UserWrapper wrapper,
- final List<String> anyTypeClasses,
- final UserFormLayoutInfo formLayoutInfo,
- final PageReference pageRef) {
-
- super(wrapper, pageRef);
- this.anyTypeClasses = anyTypeClasses;
- this.formLayoutInfo = formLayoutInfo;
- }
-
- @Override
- protected WizardModel buildModelSteps(final AnyWrapper<UserTO> modelObject, final WizardModel wizardModel) {
- wizardModel.add(new UserDetails(
- UserWrapper.class.cast(modelObject),
- mode == AjaxWizard.Mode.TEMPLATE,
- UserFormLayoutInfo.class.cast(formLayoutInfo).isPasswordManagement()));
-
- if (formLayoutInfo.isAuxClasses()) {
- wizardModel.add(new EnduserAuxClasses(modelObject, anyTypeClasses));
- }
-
- if (formLayoutInfo.isGroups()) {
- wizardModel.add(new Groups(modelObject));
- }
-
- // attributes panel steps
- if (formLayoutInfo.isPlainAttrs()) {
- wizardModel.add(new PlainAttrs(
- modelObject,
- mode,
- anyTypeClasses,
- formLayoutInfo.getWhichPlainAttrs()) {
-
- private static final long serialVersionUID = 8167894751609598306L;
-
- @Override
- public PageReference getPageReference() {
- return pageRef;
- }
-
- });
- }
- if (formLayoutInfo.isDerAttrs()) {
- wizardModel.add(new DerAttrs(modelObject, anyTypeClasses, formLayoutInfo.getWhichDerAttrs()));
- }
- if (formLayoutInfo.isVirAttrs()) {
- wizardModel.add(new VirAttrs(modelObject, anyTypeClasses, formLayoutInfo.getWhichVirAttrs()));
- }
- if (formLayoutInfo.isResources()) {
- wizardModel.add(new Resources(modelObject));
- }
- if (SyncopeWebApplication.get().isCaptchaEnabled()) {
- // add captcha
- captcha = new Captcha();
- captcha.setOutputMarkupId(true);
- wizardModel.add(captcha);
- }
-
- return wizardModel;
- }
-
- @Override
- protected long getMaxWaitTimeInSeconds() {
- return SyncopeWebApplication.get().getMaxWaitTimeInSeconds();
- }
-
- @Override
- protected void sendError(final Exception exception) {
- SyncopeEnduserSession.get().onException(exception);
- }
-
- @Override
- protected void sendWarning(final String message) {
- SyncopeEnduserSession.get().warn(message);
- }
-
- @Override
- protected Future<Pair<Serializable, Serializable>> execute(
- final Callable<Pair<Serializable, Serializable>> future) {
- return SyncopeEnduserSession.get().execute(future);
- }
-
- @Override
- public AjaxWizard<AnyWrapper<UserTO>> build(final String id, final AjaxWizard.Mode mode) {
- this.mode = mode;
-
- // get the specified item if available
- final AnyWrapper<UserTO> modelObject = newModelObject();
-
- return new AjaxWizard<AnyWrapper<UserTO>>(
- id, modelObject, buildModelSteps(modelObject, new WizardModel()), mode, this.pageRef) {
-
- private static final long serialVersionUID = 7770507663760640735L;
-
- @Override
- protected void onCancelInternal() {
- AnyWizardBuilder.this.onCancelInternal(modelObject);
- }
-
- @Override
- protected Pair<Serializable, Serializable> onApplyInternal(final AjaxRequestTarget target) {
- Serializable res = AnyWizardBuilder.this.onApplyInternal(modelObject);
-
- Serializable payload;
- switch (mode) {
- case CREATE:
- payload = getCreateCustomPayloadEvent(res, target);
- break;
- case EDIT:
- case TEMPLATE:
- payload = getEditCustomPayloadEvent(res, target);
- break;
- default:
- payload = null;
- }
-
- return Pair.of(payload, res);
- }
-
- @Override
- protected long getMaxWaitTimeInSeconds() {
- return AnyWizardBuilder.this.getMaxWaitTimeInSeconds();
- }
-
- @Override
- protected void sendError(final Exception exception) {
- SyncopeEnduserSession.get().onException(exception);
- }
-
- @Override
- protected void sendWarning(final String message) {
- AnyWizardBuilder.this.sendWarning(message);
- }
-
- @Override
- protected Future<Pair<Serializable, Serializable>> execute(
- final Callable<Pair<Serializable, Serializable>> future) {
- return AnyWizardBuilder.this.execute(future);
- }
-
- @Override
- protected Component newButtonBar(final String id) {
- return new AjaxWizardMgtButtonBar<>(id, this, mode) {
-
- private static final long serialVersionUID = -3041152400413815333L;
-
- @Override
- protected FinishButton newFinishButton(final String id, final IWizard wizard) {
- return new FinishButton(id, wizard) {
-
- private static final long serialVersionUID = 864248301720764819L;
-
- @Override
- public boolean isEnabled() {
- switch (mode) {
- case EDIT:
- case TEMPLATE:
- return true;
- case READONLY:
- return false;
- default:
- if (!completed) {
- final IWizardStep activeStep = getWizardModel().getActiveStep();
- completed = (activeStep != null)
- && getWizardModel().isLastStep(activeStep)
- && super.isEnabled();
- }
- return completed;
- }
- }
-
- @Override
- public boolean isVisible() {
- switch (mode) {
- case READONLY:
- return false;
- default:
- return true;
- }
- }
-
- @Override
- public void onClick() {
- IWizardModel wizardModel = getWizardModel();
- IWizardStep activeStep = wizardModel.getActiveStep();
-
- // let the step apply any state
- activeStep.applyState();
-
- // if the step completed after applying the state, notify the wizard
- if (activeStep.isComplete()
- && SyncopeWebApplication.get().isCaptchaEnabled()
- && !getWizardModel().isLastStep(activeStep)) {
- // go to last step
- getWizardModel().last();
- } else if (activeStep.isComplete()) {
- getWizardModel().finish();
- } else {
- error(getLocalizer().getString(
- "org.apache.wicket.extensions.wizard.FinishButton.step.did.not.complete",
- this));
- }
- }
- };
- }
-
- };
- }
-
- }.setEventSink(eventSink).addOuterObject(outerObjects);
- }
-}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/Captcha.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/Captcha.java
deleted file mode 100644
index c46755c..0000000
--- a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/Captcha.java
+++ /dev/null
@@ -1,49 +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.enduser.wizards.any;
-
-import org.apache.syncope.client.enduser.SyncopeWebApplication;
-import org.apache.wicket.extensions.wizard.WizardModel;
-import org.apache.wicket.extensions.wizard.WizardStep;
-
-public class Captcha extends WizardStep implements WizardModel.ICondition {
-
- private static final long serialVersionUID = 702900610508752856L;
-
- private final CaptchaPanel<Void> captchaPanel;
-
- public Captcha() {
- captchaPanel = new CaptchaPanel<>("captchaPanel");
- captchaPanel.setOutputMarkupId(true);
- add(captchaPanel);
- }
-
- public boolean captchaCheck() {
- return captchaPanel.captchaCheck();
- }
-
- public void reload() {
- captchaPanel.reload();
- }
-
- @Override
- public boolean evaluate() {
- return SyncopeWebApplication.get().isCaptchaEnabled();
- }
-}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.java
deleted file mode 100644
index bdd6f44..0000000
--- a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.java
+++ /dev/null
@@ -1,45 +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.enduser.wizards.any;
-
-import org.apache.syncope.client.ui.commons.wizards.any.AbstractAuxClasses;
-import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
-import java.util.List;
-import java.util.stream.Collectors;
-import org.apache.syncope.client.enduser.rest.SyncopeRestClient;
-import org.apache.syncope.common.lib.to.AnyTO;
-import org.apache.syncope.common.lib.to.AnyTypeClassTO;
-
-public class EnduserAuxClasses extends AbstractAuxClasses {
-
- private static final long serialVersionUID = 552437609667518888L;
-
- public <T extends AnyTO> EnduserAuxClasses(final AnyWrapper<T> modelObject, final List<String> anyTypeClasses) {
- super(modelObject, anyTypeClasses);
- }
-
- @Override
- protected final List<AnyTypeClassTO> listAnyTypecClasses() {
- return SyncopeRestClient.listAnyTypeClasses().stream().map(name -> {
- AnyTypeClassTO anyTypeClassTO = new AnyTypeClassTO();
- anyTypeClassTO.setKey(name);
- return anyTypeClassTO;
- }).collect(Collectors.toList());
- }
-}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/Resources.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/Resources.java
deleted file mode 100644
index c4e7857..0000000
--- a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/Resources.java
+++ /dev/null
@@ -1,40 +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.enduser.wizards.any;
-
-import org.apache.syncope.client.enduser.SyncopeEnduserSession;
-import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
-import org.apache.syncope.client.ui.commons.wizards.any.AbstractResources;
-import org.apache.syncope.common.lib.to.AnyTO;
-import org.apache.syncope.common.rest.api.service.SyncopeService;
-
-public class Resources extends AbstractResources {
-
- private static final long serialVersionUID = 702900610508752856L;
-
- public <T extends AnyTO> Resources(final AnyWrapper<T> modelObject) {
- super(modelObject);
- }
-
- @Override
- public boolean evaluate() {
- available.setObject(SyncopeEnduserSession.get().getService(SyncopeService.class).platform().getResources());
- return !available.getObject().isEmpty();
- }
-}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/UserDetails.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/UserDetails.java
deleted file mode 100644
index 8f07432..0000000
--- a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/UserDetails.java
+++ /dev/null
@@ -1,235 +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.enduser.wizards.any;
-
-import de.agilecoders.wicket.extensions.markup.html.bootstrap.form.password.strength.PasswordStrengthBehavior;
-import de.agilecoders.wicket.extensions.markup.html.bootstrap.form.password.strength.PasswordStrengthConfig;
-import java.util.List;
-import java.util.stream.Collectors;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.syncope.client.enduser.rest.RealmRestClient;
-import org.apache.syncope.client.enduser.rest.SecurityQuestionRestClient;
-import org.apache.syncope.client.ui.commons.Constants;
-import org.apache.syncope.client.ui.commons.ajax.markup.html.LabelInfo;
-import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
-import org.apache.syncope.client.ui.commons.wicket.markup.html.bootstrap.tabs.Accordion;
-import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
-import org.apache.syncope.client.ui.commons.markup.html.form.FieldPanel;
-import org.apache.syncope.client.ui.commons.wizards.any.PasswordPanel;
-import org.apache.syncope.client.ui.commons.wizards.any.UserWrapper;
-import org.apache.syncope.common.lib.to.RealmTO;
-import org.apache.syncope.common.lib.to.SecurityQuestionTO;
-import org.apache.syncope.common.lib.to.UserTO;
-import org.apache.wicket.Component;
-import org.apache.wicket.ajax.AjaxEventBehavior;
-import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.ajax.markup.html.AjaxLink;
-import org.apache.wicket.extensions.markup.html.tabs.AbstractTab;
-import org.apache.wicket.extensions.markup.html.tabs.ITab;
-import org.apache.wicket.extensions.wizard.WizardStep;
-import org.apache.wicket.markup.ComponentTag;
-import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.markup.html.form.IChoiceRenderer;
-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.PropertyModel;
-import org.apache.wicket.model.ResourceModel;
-
-public class UserDetails extends WizardStep {
-
- private static final long serialVersionUID = 6592027822510220463L;
-
- private static final String PASSWORD_CONTENT_PATH = "body:content";
-
- private final FieldPanel<String> realm;
-
- protected final AjaxTextFieldPanel username;
-
- private final FieldPanel<String> securityQuestion;
-
- private final FieldPanel<String> securityAnswer;
-
- protected final UserTO userTO;
-
- @SuppressWarnings({ "unchecked", "rawtypes" })
- public UserDetails(
- final UserWrapper wrapper,
- final boolean templateMode,
- final boolean showPasswordManagement) {
-
- super();
-
- userTO = wrapper.getInnerObject();
- // ------------------------
- // Username
- // ------------------------
- username = new AjaxTextFieldPanel(Constants.USERNAME_FIELD_NAME, Constants.USERNAME_FIELD_NAME,
- new PropertyModel<>(userTO, Constants.USERNAME_FIELD_NAME), false);
-
- if (wrapper.getPreviousUserTO() != null && StringUtils.
- compare(wrapper.getPreviousUserTO().getUsername(), wrapper.getInnerObject().getUsername()) != 0) {
- username.showExternAction(new LabelInfo("externalAction", wrapper.getPreviousUserTO().getUsername()));
- }
-
- if (templateMode) {
- username.enableJexlHelp();
- } else {
- username.addRequiredLabel();
- }
- add(username);
- // ------------------------
-
- // ------------------------
- // Realm
- // ------------------------
- realm = new AjaxDropDownChoicePanel<>(
- "destinationRealm", "destinationRealm", new PropertyModel<>(userTO, "realm"), false);
-
- ((AjaxDropDownChoicePanel<String>) realm).setChoices(
- RealmRestClient.list().stream().map(RealmTO::getFullPath).collect(Collectors.toList()));
- add(realm);
-
- // ------------------------
- // Password
- // ------------------------
- Model<Integer> model = Model.of(-1);
-
- Accordion accordion = new Accordion("accordionPanel", List.of(
- new AbstractTab(new ResourceModel("password.change", "Change password")) {
-
- private static final long serialVersionUID = 1037272333056449378L;
-
- @Override
- public Panel getPanel(final String panelId) {
- EditUserPasswordPanel panel = new EditUserPasswordPanel(panelId, wrapper, templateMode);
- panel.setEnabled(model.getObject() >= 0);
- return panel;
- }
- }), model) {
-
- private static final long serialVersionUID = -2898628183677758699L;
-
- @Override
- protected Component newTitle(final String markupId, final ITab tab, final Accordion.State state) {
- return new AjaxLink<Integer>(markupId) {
-
- private static final long serialVersionUID = 7021195294339489084L;
-
- @Override
- protected void onComponentTag(final ComponentTag tag) {
- super.onComponentTag(tag);
- tag.put("style", "color: #337ab7");
- }
-
- @Override
- public void onClick(final AjaxRequestTarget target) {
- model.setObject(model.getObject() == 0 ? -1 : 0);
- Component passwordPanel = getParent().get(PASSWORD_CONTENT_PATH);
- passwordPanel.setEnabled(model.getObject() >= 0);
- target.add(passwordPanel);
- }
- }.setBody(new ResourceModel("password.change", "Change password ..."));
- }
- };
-
- accordion.setOutputMarkupId(true);
- accordion.setVisible(showPasswordManagement);
- add(accordion);
- // ------------------------
-
- // ------------------------
- // Security Question
- // ------------------------
- securityQuestion = new AjaxDropDownChoicePanel("securityQuestion", "securityQuestion", new PropertyModel<>(
- userTO, "securityQuestion"));
- ((AjaxDropDownChoicePanel) securityQuestion).setNullValid(true);
-
- final List<SecurityQuestionTO> securityQuestions = SecurityQuestionRestClient.list();
- ((AjaxDropDownChoicePanel<String>) securityQuestion).setChoices(securityQuestions.stream().map(
- SecurityQuestionTO::getKey).collect(Collectors.toList()));
- ((AjaxDropDownChoicePanel<String>) securityQuestion).setChoiceRenderer(
- new IChoiceRenderer<String>() {
-
- private static final long serialVersionUID = -4421146737845000747L;
-
- @Override
- public Object getDisplayValue(final String value) {
- return securityQuestions.stream().filter(sq -> value.equals(sq.getKey()))
- .map(SecurityQuestionTO::getContent).findFirst().orElse(null);
- }
-
- @Override
- public String getIdValue(final String value, final int index) {
- return value;
- }
-
- @Override
- public String getObject(
- final String id,
- final IModel<? extends List<? extends String>> choices) {
- return id;
- }
- });
-
- securityQuestion.add(new AjaxEventBehavior(Constants.ON_CHANGE) {
-
- private static final long serialVersionUID = 192359260308762078L;
-
- @Override
- protected void onEvent(final AjaxRequestTarget target) {
- securityAnswer.setEnabled(StringUtils.isNotBlank(securityQuestion.getModelObject()));
- target.add(securityAnswer);
- }
- });
-
- add(securityQuestion);
- // ------------------------
-
- // ------------------------
- // Security Answer
- // ------------------------
- securityAnswer =
- new AjaxTextFieldPanel("securityAnswer", "securityAnswer",
- new PropertyModel<>(userTO, "securityAnswer"), false);
- add(securityAnswer.setOutputMarkupId(true).setOutputMarkupPlaceholderTag(true).setEnabled(StringUtils.
- isNotBlank(securityQuestion.getModelObject())));
- // ------------------------
- }
-
- public static class EditUserPasswordPanel extends Panel {
-
- private static final long serialVersionUID = -8198836979773590078L;
-
- public EditUserPasswordPanel(
- final String id,
- final UserWrapper wrapper,
- final boolean templateMode) {
- super(id);
- setOutputMarkupId(true);
- add(new Label("warning", new ResourceModel("password.change.warning")));
- add(new PasswordPanel("passwordPanel", wrapper, templateMode, new PasswordStrengthBehavior(
- new PasswordStrengthConfig()
- .withDebug(true)
- .withShowVerdictsInsideProgressBar(true)
- .withShowProgressBar(true))));
- }
-
- }
-}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/UserWizardBuilder.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/UserWizardBuilder.java
deleted file mode 100644
index 714cacb..0000000
--- a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/UserWizardBuilder.java
+++ /dev/null
@@ -1,133 +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.enduser.wizards.any;
-
-import java.io.Serializable;
-import java.util.List;
-import java.util.Optional;
-
-import org.apache.commons.lang3.StringUtils;
-import org.apache.syncope.client.ui.commons.layout.UserForm;
-import org.apache.syncope.client.enduser.layout.UserFormLayoutInfo;
-import org.apache.syncope.client.enduser.rest.UserSelfRestClient;
-import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
-import org.apache.syncope.client.ui.commons.wizards.any.UserWrapper;
-import org.apache.syncope.client.ui.commons.wizards.exception.CaptchaNotMatchingException;
-import org.apache.syncope.common.lib.AnyOperations;
-import org.apache.syncope.common.lib.EntityTOUtils;
-import org.apache.syncope.common.lib.request.PasswordPatch;
-import org.apache.syncope.common.lib.request.UserCR;
-import org.apache.syncope.common.lib.request.UserUR;
-import org.apache.syncope.common.lib.to.ProvisioningResult;
-import org.apache.syncope.common.lib.to.UserTO;
-import org.apache.wicket.PageReference;
-
-public class UserWizardBuilder extends AnyWizardBuilder implements UserForm {
-
- private static final long serialVersionUID = 6716803168859873877L;
-
- protected final UserSelfRestClient userSelfRestClient = new UserSelfRestClient();
-
- /**
- * Constructor to be used for templating only.
- *
- * @param anyTypeClasses any type classes.
- * @param formLayoutInfo form layout.
- * @param pageRef reference page.
- */
- public UserWizardBuilder(
- final List<String> anyTypeClasses,
- final UserFormLayoutInfo formLayoutInfo,
- final PageReference pageRef) {
-
- super(new UserWrapper(null), anyTypeClasses, formLayoutInfo, pageRef);
- }
-
- /**
- * Constructor to be used for Approval and Remediation details only.
- *
- * @param previousUserTO previous user status.
- * @param userTO new user status to be approved.
- * @param anyTypeClasses any type classes.
- * @param formLayoutInfo from layout.
- * @param pageRef reference page.
- */
- public UserWizardBuilder(
- final UserTO previousUserTO,
- final UserTO userTO,
- final List<String> anyTypeClasses,
- final UserFormLayoutInfo formLayoutInfo,
- final PageReference pageRef) {
-
- super(new UserWrapper(previousUserTO, userTO), anyTypeClasses, formLayoutInfo, pageRef);
- }
-
- @Override
- protected Serializable onApplyInternal(final AnyWrapper<UserTO> modelObject) {
- // captcha check
- if (captcha != null && captcha.evaluate() && !captcha.captchaCheck()) {
- throw new CaptchaNotMatchingException();
- }
- UserTO inner = modelObject.getInnerObject();
-
- ProvisioningResult<UserTO> result;
- if (inner.getKey() == null) {
- UserCR req = new UserCR();
- EntityTOUtils.toAnyCR(inner, req);
- req.setStorePassword(modelObject instanceof UserWrapper
- ? UserWrapper.class.cast(modelObject).isStorePasswordInSyncope()
- : StringUtils.isNotBlank(inner.getPassword()));
-
- result = UserSelfRestClient.create(req);
- } else {
- fixPlainAndVirAttrs(inner, getOriginalItem().getInnerObject());
- UserUR userUR = AnyOperations.diff(inner, getOriginalItem().getInnerObject(), false);
-
- if (StringUtils.isNotBlank(inner.getPassword())) {
- PasswordPatch passwordPatch = new PasswordPatch.Builder().
- value(inner.getPassword()).onSyncope(true).resources(inner.getResources()).build();
- userUR.setPassword(passwordPatch);
- }
-
- // update just if it is changed
- if (userUR.isEmpty()) {
- result = new ProvisioningResult<>();
- result.setEntity(inner);
- } else {
- result = userSelfRestClient.update(getOriginalItem().getInnerObject().getETagValue(), userUR);
- }
- }
-
- return result;
- }
-
- /**
- * Overrides default setItem() in order to clean statusModel as well.
- *
- * @param item item to be set.
- * @return the current wizard.
- */
- @Override
- public UserWizardBuilder setItem(final AnyWrapper<UserTO> item) {
- super.setItem(Optional.ofNullable(item)
- .map(userTOAnyWrapper -> new UserWrapper(userTOAnyWrapper.getInnerObject())).orElse(null));
- return this;
- }
-
-}
diff --git a/client/idrepo/enduser/src/main/resources/META-INF/resources/css/AdminLTE_plugins/dataTables.bootstrap4.min.css b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/AdminLTE_plugins/dataTables.bootstrap4.min.css
new file mode 100644
index 0000000..f1930be
--- /dev/null
+++ b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/AdminLTE_plugins/dataTables.bootstrap4.min.css
@@ -0,0 +1 @@
+table.dataTable{clear:both;margin-top:6px !important;margin-bottom:6px !important;max-width:none !important;border-collapse:separate !important;border-spacing:0}table.dataTable td,table.dataTable th{-webkit-box-sizing:content-box;box-sizing:content-box}table.dataTable td.dataTables_empty,table.dataTable th.dataTables_empty{text-align:center}table.dataTable.nowrap th,table.dataTable.nowrap td{white-space:nowrap}div.dataTables_wrapper div.dataTables_length label{font-weight:normal;text-align:left;white-space:nowrap}div.dataTables_wrapper div.dataTables_length select{width:auto;display:inline-block}div.dataTables_wrapper div.dataTables_filter{text-align:right}div.dataTables_wrapper div.dataTables_filter label{font-weight:normal;white-space:nowrap;text-align:left}div.dataTables_wrapper div.dataTables_filter input{margin-left:0.5em;display:inline-block;width:auto}div.dataTables_wrapper div.dataTables_info{padding-top:0.85em;white-space:nowrap}div.dataTables_wrapper div.dataTables_paginate{margin:0;white-space:nowrap;text-align:right}div.dataTables_wrapper div.dataTables_paginate ul.pagination{margin:2px 0;white-space:nowrap;justify-content:flex-end}div.dataTables_wrapper div.dataTables_processing{position:absolute;top:50%;left:50%;width:200px;margin-left:-100px;margin-top:-26px;text-align:center;padding:1em 0}table.dataTable thead>tr>th.sorting_asc,table.dataTable thead>tr>th.sorting_desc,table.dataTable thead>tr>th.sorting,table.dataTable thead>tr>td.sorting_asc,table.dataTable thead>tr>td.sorting_desc,table.dataTable thead>tr>td.sorting{padding-right:30px}table.dataTable thead>tr>th:active,table.dataTable thead>tr>td:active{outline:none}table.dataTable thead .sorting,table.dataTable thead .sorting_asc,table.dataTable thead .sorting_desc,table.dataTable thead .sorting_asc_disabled,table.dataTable thead .sorting_desc_disabled{cursor:pointer;position:relative}table.dataTable thead .sorting:before,table.dataTable thead .sorting:after,table.dataTable thead .sorting_asc:before,table.dataTable thead .sorting_asc:after,table.dataTable thead .sorting_desc:before,table.dataTable thead .sorting_desc:after,table.dataTable thead .sorting_asc_disabled:before,table.dataTable thead .sorting_asc_disabled:after,table.dataTable thead .sorting_desc_disabled:before,table.dataTable thead .sorting_desc_disabled:after{position:absolute;bottom:0.9em;display:block;opacity:0.3}table.dataTable thead .sorting:before,table.dataTable thead .sorting_asc:before,table.dataTable thead .sorting_desc:before,table.dataTable thead .sorting_asc_disabled:before,table.dataTable thead .sorting_desc_disabled:before{right:1em;content:"\2191"}table.dataTable thead .sorting:after,table.dataTable thead .sorting_asc:after,table.dataTable thead .sorting_desc:after,table.dataTable thead .sorting_asc_disabled:after,table.dataTable thead .sorting_desc_disabled:after{right:0.5em;content:"\2193"}table.dataTable thead .sorting_asc:before,table.dataTable thead .sorting_desc:after{opacity:1}table.dataTable thead .sorting_asc_disabled:before,table.dataTable thead .sorting_desc_disabled:after{opacity:0}div.dataTables_scrollHead table.dataTable{margin-bottom:0 !important}div.dataTables_scrollBody table{border-top:none;margin-top:0 !important;margin-bottom:0 !important}div.dataTables_scrollBody table thead .sorting:before,div.dataTables_scrollBody table thead .sorting_asc:before,div.dataTables_scrollBody table thead .sorting_desc:before,div.dataTables_scrollBody table thead .sorting:after,div.dataTables_scrollBody table thead .sorting_asc:after,div.dataTables_scrollBody table thead .sorting_desc:after{display:none}div.dataTables_scrollBody table tbody tr:first-child th,div.dataTables_scrollBody table tbody tr:first-child td{border-top:none}div.dataTables_scrollFoot>.dataTables_scrollFootInner{box-sizing:content-box}div.dataTables_scrollFoot>.dataTables_scrollFootInner>table{margin-top:0 !important;border-top:none}@media screen and (max-width: 767px){div.dataTables_wrapper div.dataTables_length,div.dataTables_wrapper div.dataTables_filter,div.dataTables_wrapper div.dataTables_info,div.dataTables_wrapper div.dataTables_paginate{text-align:center}}table.dataTable.table-sm>thead>tr>th{padding-right:20px}table.dataTable.table-sm .sorting:before,table.dataTable.table-sm .sorting_asc:before,table.dataTable.table-sm .sorting_desc:before{top:5px;right:0.85em}table.dataTable.table-sm .sorting:after,table.dataTable.table-sm .sorting_asc:after,table.dataTable.table-sm .sorting_desc:after{top:5px}table.table-bordered.dataTable th,table.table-bordered.dataTable td{border-left-width:0}table.table-bordered.dataTable th:last-child,table.table-bordered.dataTable th:last-child,table.table-bordered.dataTable td:last-child,table.table-bordered.dataTable td:last-child{border-right-width:0}table.table-bordered.dataTable tbody th,table.table-bordered.dataTable tbody td{border-bottom-width:0}div.dataTables_scrollHead table.table-bordered{border-bottom-width:0}div.table-responsive>div.dataTables_wrapper>div.row{margin:0}div.table-responsive>div.dataTables_wrapper>div.row>div[class^="col-"]:first-child{padding-left:0}div.table-responsive>div.dataTables_wrapper>div.row>div[class^="col-"]:last-child{padding-right:0}
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/SelfUpdate.java b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/accessibility.css
similarity index 70%
copy from client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/SelfUpdate.java
copy to client/idrepo/enduser/src/main/resources/META-INF/resources/css/accessibility.css
index 7c86c2d..21b9201 100644
--- a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/SelfUpdate.java
+++ b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/accessibility.css
@@ -16,16 +16,29 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.syncope.client.enduser.pages;
-import org.apache.wicket.request.mapper.parameter.PageParameters;
+.btn-accessibility {
+ position: absolute;
+ right: 0;
+ font-size: 12px;
+ padding: 15px 15px 0 0;
+}
-public class SelfUpdate extends BaseEnduserWebPage {
+.btn-accessibility i {
+ font-size: 30px;
+}
- private static final long serialVersionUID = 164651008547631054L;
+.btn-accessibility:hover {
+ cursor:pointer;
+}
- public SelfUpdate(final PageParameters parameters) {
- super(parameters);
- }
+.control-sidebar-menu a:focus {
+ outline: 1px #949494 solid;
+}
+#change_contrast {
+ top: 0;
+}
+#change_fontSize {
+ top: 40px;
}
diff --git a/client/idrepo/enduser/src/main/resources/META-INF/resources/css/accessibility/accessibilityFont.css b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/accessibility/accessibilityFont.css
new file mode 100644
index 0000000..da26456
--- /dev/null
+++ b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/accessibility/accessibilityFont.css
@@ -0,0 +1,101 @@
+/*
+ * 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.
+ */
+
+body,
+p {
+ font-size: 200%;
+}
+
+.menu a,
+.treeview-menu a,
+.control-sidebar-subheading {
+ font-size: 80% !important;
+}
+
+.box-header > .fa,
+.box-header > .glyphicon,
+.box-header > .ion, .box-header .box-title,
+.dropdown-toggle .filter-option,
+.dropdown-menu a,
+.menu-info span,
+.user-header,
+.header,
+.modal-title,
+.small-box p,
+.alert-widget,
+.alert-widget > a > .label,
+.alert h4,
+#mappings .fa,
+.popover-content,
+.box .dropdown-toggle .glyphicon,
+.box-header button,
+.toggle .toggle-group .btn,
+.input-group .form-control label {
+ font-size: 120%;
+}
+
+input,
+select,
+.footer a,
+.modal-footer button,
+.dropdown-menu:not([role='menu']),
+.dropdown-menu > li.header,
+div#tablehandling ul.menu i,
+.content-header > .breadcrumb,
+.btn-primary:not(.btn-circle),
+.modal-content .box .dialog pre {
+ font-size: 100% !important;
+}
+
+#topology .window {
+ height: 90px;
+}
+
+.dataTables_length select {
+ font-size: 85% !important;
+}
+
+button.close {
+ font-size: 2em;
+}
+
+.details-footer .information {
+ font-size: 12px;
+}
+
+.btn-file i,
+.btn-file span,
+.input-group-btn button.btn-primary {
+ font-size: 20px !important;
+}
+
+.checkbox input[type=checkbox],
+.checkbox-inline input[type=checkbox],
+.radio input[type=radio],
+.radio-inline input[type=radio],
+input[type=checkbox],
+input[type=radio] {
+ width: 20px;
+ height: 20px;
+}
+
+.k-timepicker,
+.k-datepicker {
+ width: 200px !important;
+}
diff --git a/client/idrepo/enduser/src/main/resources/META-INF/resources/css/accessibility/accessibilityHC.css b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/accessibility/accessibilityHC.css
new file mode 100644
index 0000000..aa4d5b9
--- /dev/null
+++ b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/accessibility/accessibilityHC.css
@@ -0,0 +1,296 @@
+/*
+ * 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.
+ */
+
+/* General
+============================================================================= */
+.content-wrapper,
+.content-wrapper .box,
+.modal-content,
+.modal-header,
+.background-footer,
+input:not(:disabled):not([type="file"]),
+select,
+select option,
+button:not(.close),
+.table .sorting,
+.dataTables_paginate a,
+.modal-footer,
+.box-header,
+.dropdown-menu,
+.main-footer,
+.circular-actions a,
+.k-select,
+.file-caption.kv-fileinput-caption {
+ color: #f7f7f7 !important;
+ background-color: #0f1417 !important;
+}
+
+
+.dataTable thead th:after,
+.close {
+ color: #f7f7f7 !important;
+ opacity: 0.8 !important;
+}
+
+
+.input-group-addon a,
+.input-group-addon i,
+.dropdown-menu > li:not(.disabled) > a:hover,
+.dropdown-menu > li:not(.disabled) > a:hover span,
+.dropdown-menu > li:not(.disabled) > a:focus,
+.dropdown-menu > li:not(.disabled) > a:focus span,
+#startAtContainer .input-group-addon span,
+#startAtContainer .k-widget span,
+#startAtContainer .k-widget i,
+#startAtContainer .k-widget input,
+.modal-footer i,
+.navbar-nav > .user-menu > .dropdown-menu > .user-footer .btn-default,
+.content-wrapper .nav-tabs a,
+.wrapper .content-wrapper .nav.nav-tabs li.active a span,
+.wrapper .content-wrapper .nav.nav-tabs li.active a,
+.wrapper .content-wrapper .nav.nav-tabs li a:hover span,
+.wrapper .content-wrapper .nav.nav-tabs li a:hover,
+.wrapper .content-wrapper .nav.nav-tabs li a:active span,
+.wrapper .content-wrapper .nav.nav-tabs li a:active,
+.wrapper .content-wrapper .nav.nav-tabs li a:focus span,
+.wrapper .content-wrapper .nav.nav-tabs li a:focus,
+.wrapper .content-wrapper .tab-content .btn-primary .fa-download {
+ color: #000000 !important;
+}
+
+
+.content-wrapper a:not(.btn-primary),
+.content-wrapper span:not(.label-info):not([role="presentation"]):not([class^='cm-']),
+.content-wrapper p,
+.content-wrapper .box-title a,
+.realm-choice .dropdown-menu > li:not(.disabled) > a:hover,
+.realm-choice .dropdown-menu > li:not(.disabled) > a:hover span,
+.realm-choice .dropdown-menu > li:not(.disabled) > a:focus,
+.realm-choice .dropdown-menu > li:not(.disabled) > a:focus span,
+.box-header,
+.breadcrumb .active,
+table tbody tr:hover button span,
+.dropdown-menu > li > a,
+.modal-header button,
+.circular-actions a i,
+.wizard-form .input-group-addon i,
+#startAtContainer .input-group-addon i,
+.attribute .input-group-addon i {
+ color: #f7f7f7 !important;
+}
+
+
+.box.box-primary {
+ border-top-color: #f7f7f7;
+}
+
+
+img,
+.content-wrapper div.btn.btn-file span.hidden-xs {
+ background-color: #f7f7f7;
+ color: #000000 !important;
+}
+.btn-primary,
+.callout.callout-info,
+.alert-info,
+.label-info,
+.modal-info .modal-body {
+ background-color: #f7f7f7 !important;
+ color: #000000 !important;
+}
+
+
+.logo img,
+.modal-content .input-group .input-group-addon {
+ background-color: transparent;
+}
+
+
+.modal-dialog {
+ border: 2px solid white;
+}
+
+
+#veil:not(:required):after {
+ -webkit-box-shadow: #f7f7f7 1.5em 0 0 0,
+ #f7f7f7 1.1em 1.1em 0 0,
+ #f7f7f7 0 1.5em 0 0,
+ #f7f7f7 -1.1em 1.1em 0 0,
+ rgba(0, 0, 0, 0.5) -1.5em 0 0 0,
+ rgba(0, 0, 0, 0.5) -1.1em -1.1em 0 0,
+ #f7f7f7 0 -1.5em 0 0,
+ #f7f7f7 1.1em -1.1em 0 0;
+ box-shadow: #f7f7f7 1.5em 0 0 0,
+ #f7f7f7 1.1em 1.1em 0 0,
+ #f7f7f7 0 1.5em 0 0,
+ #f7f7f7 -1.1em 1.1em 0 0,
+ #f7f7f7 -1.5em 0 0 0,
+ #f7f7f7 -1.1em -1.1em 0 0,
+ #f7f7f7 0 -1.5em 0 0,
+ #f7f7f7 1.1em -1.1em 0 0;
+}
+
+
+.input-group input:disabled,
+.input-group input[disabled],
+.control-sidebar-dark .control-sidebar-menu > li > a:hover,
+.table-hover > tbody > tr:hover,
+.skin-blue .main-header .navbar .sidebar-toggle:hover,
+.main-header .navbar .sidebar-toggle:hover,
+.skin-blue .main-header .logo:hover,
+.main-header .logo:hover,
+div.toggle-menu ul li:hover,
+.skin-blue .main-header .navbar .nav > li > a:hover,
+.skin-blue .main-header .navbar .nav > li > a:active,
+.skin-blue .main-header .navbar .nav > li > a:focus,
+.skin-blue .main-header .navbar .nav .open > a:hover,
+.skin-blue .main-header .navbar .nav .open > a:focus,
+.skin-blue .sidebar-menu > li:hover > a,
+.skin-blue .sidebar-menu > li.active > a,
+.dropdown-menu > li > a:hover,
+.dropdown-menu > li > a:focus,
+.dropdown-menu > li > a:hover,
+.k-block,
+.k-draghandle,
+.k-grid-header,
+.k-grouping-header,
+.k-header,
+.k-pager-wrap,
+.k-toolbar,
+.k-treemap-tile,
+.k-picker-wrap,
+.k-state-disabled,
+.km-pane-wrapper .k-header {
+ background-color: rgba(108, 115, 117, 0.55);
+}
+
+
+.sidebar-mini .main-header .navbar {
+ background-color: #222d32; /* color from 'skin-blue' */
+ border-bottom: 1px white solid;
+ box-sizing: border-box;
+}
+.sidebar-mini .main-header .logo,
+div.toggle-menu,
+.skin-blue .main-header li.user-header {
+ background-color: #222d32;
+}
+
+
+div.toggle-menu {
+ border: 1px solid #f7f7f7;
+}
+
+
+a,
+.pagination > .active > a,
+.pagination > .active > a:focus,
+.pagination > .active > a:hover,
+.pagination > .active > span,
+.pagination > .active > span:focus,
+.pagination > .active > span:hover {
+ border-color: #76abd9;
+}
+a {
+ color: #76abd9;
+}
+
+
+.logs button.btn-primary {
+ border-color: #f7f7f7;
+}
+.logs button.btn-primary:hover {
+ border-color: #adadad;
+}
+div.infolabel,
+.input-group input:disabled,
+.input-group input[disabled] {
+ color: #d2d2d2;
+}
+
+
+.bg-red,
+.callout.callout-danger,
+.alert-danger,
+.alert-error,
+.label-danger,
+.modal-danger .modal-body,
+.btn-danger.active,
+.btn-danger:active,
+.open>.dropdown-toggle.btn-danger {
+ background-color: #942819 !important;
+}
+.bg-yellow {
+ background-color: #6F4706 !important;
+}
+.bg-green,
+.copy-clipboard-feedback,
+.btn-success,
+.callout.callout-success,
+.alert-success,
+.label-success,
+.modal-success .modal-body {
+ background-color: #005C32 !important;
+}
+.bg-aqua {
+ background-color: #004E61 !important;
+}
+.bg-yellow,
+.callout.callout-warning,
+.alert-warning,
+.label-warning,
+.modal-warning .modal-body {
+ background-color: #6F4706 !important;
+}
+.callout.callout-warning {
+ border-color: #6F4706;
+}
+
+
+.bootstrap-select .btn.btn-default {
+ background-color: rgba(101, 101, 101, 0.7) !important;
+}
+
+
+/* Login page
+============================================================================= */
+.login-body {
+ background-image: linear-gradient(rgb(31, 109, 142), #004626);
+}
+
+.login-logo {
+ background: transparent;
+}
+
+.btn-accessibility {
+ color: #f7f7f7 !important;
+}
+
+.form-signin .btn-primary,
+.form-signin .btn-primary {
+ border: 2px solid white;
+}
+.form-signin .btn-primary.focus,
+.form-signin .btn-primary:focus {
+ border-color: #8c8c8c;
+}
+
+.login-card {
+ background-color: #0f1417;
+}
\ No newline at end of file
diff --git a/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts.css b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts.css
new file mode 100644
index 0000000..da7bdf8
--- /dev/null
+++ b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts.css
@@ -0,0 +1,89 @@
+/*
+ * 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.
+ */
+
+/* source-sans-pro-300 - latin-ext_cyrillic_latin_cyrillic-ext */
+@font-face {
+ font-family: 'Source Sans Pro';
+ font-style: normal;
+ font-weight: 300;
+ src: local('Source Sans Pro Light'), local('SourceSansPro-Light'),
+ url('./fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-300.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
+ url('./fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-300.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
+}
+
+/* source-sans-pro-300italic - latin-ext_cyrillic_latin_cyrillic-ext */
+@font-face {
+ font-family: 'Source Sans Pro';
+ font-style: italic;
+ font-weight: 300;
+ src: local('Source Sans Pro Light Italic'), local('SourceSansPro-LightItalic'),
+ url('./fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-300italic.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
+ url('./fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-300italic.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
+}
+
+/* source-sans-pro-regular - latin-ext_cyrillic_latin_cyrillic-ext */
+@font-face {
+ font-family: 'Source Sans Pro';
+ font-style: normal;
+ font-weight: 400;
+ src: local('Source Sans Pro Regular'), local('SourceSansPro-Regular'),
+ url('./fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-regular.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
+ url('./fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-regular.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
+}
+
+/* source-sans-pro-italic - latin-ext_cyrillic_latin_cyrillic-ext */
+@font-face {
+ font-family: 'Source Sans Pro';
+ font-style: italic;
+ font-weight: 400;
+ src: local('Source Sans Pro Italic'), local('SourceSansPro-Italic'),
+ url('./fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-italic.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
+ url('./fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-italic.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
+}
+
+/* source-sans-pro-600 - latin-ext_cyrillic_latin_cyrillic-ext */
+@font-face {
+ font-family: 'Source Sans Pro';
+ font-style: normal;
+ font-weight: 600;
+ src: local('Source Sans Pro SemiBold'), local('SourceSansPro-SemiBold'),
+ url('./fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-600.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
+ url('./fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-600.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
+}
+
+/* source-sans-pro-600italic - latin-ext_cyrillic_latin_cyrillic-ext */
+@font-face {
+ font-family: 'Source Sans Pro';
+ font-style: italic;
+ font-weight: 600;
+ src: local('Source Sans Pro SemiBold Italic'), local('SourceSansPro-SemiBoldItalic'),
+ url('./fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-600italic.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
+ url('./fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-600italic.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
+}
+
+/* source-sans-pro-700 - latin-ext_cyrillic_latin_cyrillic-ext */
+@font-face {
+ font-family: 'Source Sans Pro';
+ font-style: normal;
+ font-weight: 700;
+ src: local('Source Sans Pro Bold'), local('SourceSansPro-Bold'),
+ url('./fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-700.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
+ url('./fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-700.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
+}
+
diff --git a/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-300.woff b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-300.woff
new file mode 100644
index 0000000..2132b5e
--- /dev/null
+++ b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-300.woff
Binary files differ
diff --git a/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-300.woff2 b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-300.woff2
new file mode 100644
index 0000000..943f826
--- /dev/null
+++ b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-300.woff2
Binary files differ
diff --git a/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-300italic.woff b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-300italic.woff
new file mode 100644
index 0000000..aa25cd3
--- /dev/null
+++ b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-300italic.woff
Binary files differ
diff --git a/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-300italic.woff2 b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-300italic.woff2
new file mode 100644
index 0000000..441997f
--- /dev/null
+++ b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-300italic.woff2
Binary files differ
diff --git a/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-600.woff b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-600.woff
new file mode 100644
index 0000000..24d2824
--- /dev/null
+++ b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-600.woff
Binary files differ
diff --git a/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-600.woff2 b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-600.woff2
new file mode 100644
index 0000000..9ec7d25
--- /dev/null
+++ b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-600.woff2
Binary files differ
diff --git a/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-600italic.woff b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-600italic.woff
new file mode 100644
index 0000000..ce5a1cc
--- /dev/null
+++ b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-600italic.woff
Binary files differ
diff --git a/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-600italic.woff2 b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-600italic.woff2
new file mode 100644
index 0000000..7ed2f82
--- /dev/null
+++ b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-600italic.woff2
Binary files differ
diff --git a/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-700.woff b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-700.woff
new file mode 100644
index 0000000..9fbfe68
--- /dev/null
+++ b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-700.woff
Binary files differ
diff --git a/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-700.woff2 b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-700.woff2
new file mode 100644
index 0000000..096dcb1
--- /dev/null
+++ b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-700.woff2
Binary files differ
diff --git a/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-italic.woff b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-italic.woff
new file mode 100644
index 0000000..c1cf1ea
--- /dev/null
+++ b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-italic.woff
Binary files differ
diff --git a/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-italic.woff2 b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-italic.woff2
new file mode 100644
index 0000000..ff006be
--- /dev/null
+++ b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-italic.woff2
Binary files differ
diff --git a/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-regular.woff b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-regular.woff
new file mode 100644
index 0000000..e8a1ac7
--- /dev/null
+++ b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-regular.woff
Binary files differ
diff --git a/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-regular.woff2 b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-regular.woff2
new file mode 100644
index 0000000..1b0bc46
--- /dev/null
+++ b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/fonts/source-sans-pro-v11-latin-ext_cyrillic_latin_cyrillic-ext-regular.woff2
Binary files differ
diff --git a/client/idrepo/enduser/src/main/resources/META-INF/resources/css/login.css b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/login.css
new file mode 100644
index 0000000..931cb47
--- /dev/null
+++ b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/login.css
@@ -0,0 +1,141 @@
+/*
+ * 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.
+ */
+body, html {
+ height: 100% !important;
+ background-repeat: no-repeat;
+ background-image: linear-gradient(rgb(70, 30, 30), #dd4b39);
+}
+
+.card-container.card {
+ width: 350px;
+ padding: 40px 40px;
+}
+
+.btn {
+ 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);
+}
+
+.login-logo {
+ 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;
+}
+
+.form-signin #inputPassword {
+ 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;
+}
+
+.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);
+}
+
+.btn.btn-signin {
+ 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;
+}
+
+.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;
+}
diff --git a/client/idrepo/enduser/src/main/resources/META-INF/resources/css/search.css b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/search.css
new file mode 100644
index 0000000..ece4f4a
--- /dev/null
+++ b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/search.css
@@ -0,0 +1,80 @@
+/*
+ * 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.
+ */
+
+.searchBox .col-xs-12{
+ padding-left: 0px !important;
+ padding-right: 0px !important;
+}
+
+.clause{
+ display: block;
+ line-height: 34px;
+ width: 100%;
+}
+
+.clause .operator{
+ width: 65px !important;
+}
+
+.clause .operator .checkbox{
+ margin: 0px !important;
+}
+
+.clause .field {
+ line-height: 34px;
+ float: left;
+ padding: 0 3px 0px 0px;
+ display: inline-block !important;
+}
+.clause .type{
+ width: 120px !important;
+}
+
+.clause .property{
+ width: 190px;
+}
+
+.clause .comparator{
+ width: 100px;
+}
+
+.clause .comparator button{
+ width: 100px !important;
+}
+
+.clause .value{
+ width: 220px;
+}
+
+.clause .textvalue{
+ width: 45px;
+}
+
+.clause .action{
+ float: left;
+ padding: 0px 7px 0px;
+}
+
+.searchBox .input-group-addon:last-child{
+ border: 1px solid #ccc !important;
+}
+
+.searchBox .input-group{
+ margin-top: 1px;
+}
\ No newline at end of file
diff --git a/client/idrepo/enduser/src/main/resources/META-INF/resources/css/syncopeEnduser.css b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/syncopeEnduser.css
new file mode 100644
index 0000000..0b487d3
--- /dev/null
+++ b/client/idrepo/enduser/src/main/resources/META-INF/resources/css/syncopeEnduser.css
@@ -0,0 +1,1377 @@
+/*
+ * 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.
+ */
+
+pre {
+ white-space: -moz-pre-wrap; /* Mozilla, supported since 1999 */
+ white-space: -pre-wrap; /* Opera */
+ white-space: -o-pre-wrap; /* Opera */
+ white-space: pre-wrap; /* CSS3 - Text module (Candidate Recommendation) http://www.w3.org/TR/css3-text/#white-space */
+ word-wrap: break-word; /* IE 5.5+ */
+}
+
+/* Absolute Center Spinner */
+#veil {
+ display:none;
+ position: fixed;
+ z-index:99999;
+ height: 2em;
+ width: 2em;
+ overflow: show;
+ margin: auto;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ right: 0;
+}
+
+/* Transparent Overlay */
+#veil:before {
+ content: '';
+ display: block;
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background-color: rgba(0,0,0,0.3);
+}
+
+/* :not(:required) hides these rules from IE9 and below */
+#veil:not(:required) {
+ /* hide "loading..." text */
+ font: 0/0 a;
+ color: transparent;
+ text-shadow: none;
+ background-color: transparent;
+ border: 0;
+}
+
+#veil:not(:required):after {
+ content: '';
+ display: block;
+ font-size: 10px;
+ width: 1em;
+ height: 1em;
+ margin-top: -0.5em;
+ -webkit-animation: spinner 2000ms infinite linear;
+ -moz-animation: spinner 2000ms infinite linear;
+ -ms-animation: spinner 2000ms infinite linear;
+ -o-animation: spinner 2000ms infinite linear;
+ animation: spinner 2000ms infinite linear;
+ border-radius: 0.5em;
+ -webkit-box-shadow: rgba(0, 0, 0, 0.75) 1.5em 0 0 0, rgba(0, 0, 0, 0.75) 1.1em 1.1em 0 0, rgba(0, 0, 0, 0.75) 0 1.5em 0 0, rgba(0, 0, 0, 0.75) -1.1em 1.1em 0 0, rgba(0, 0, 0, 0.5) -1.5em 0 0 0, rgba(0, 0, 0, 0.5) -1.1em -1.1em 0 0, rgba(0, 0, 0, 0.75) 0 -1.5em 0 0, rgba(0, 0, 0, 0.75) 1.1em -1.1em 0 0;
+ box-shadow: rgba(0, 0, 0, 0.75) 1.5em 0 0 0, rgba(0, 0, 0, 0.75) 1.1em 1.1em 0 0, rgba(0, 0, 0, 0.75) 0 1.5em 0 0, rgba(0, 0, 0, 0.75) -1.1em 1.1em 0 0, rgba(0, 0, 0, 0.75) -1.5em 0 0 0, rgba(0, 0, 0, 0.75) -1.1em -1.1em 0 0, rgba(0, 0, 0, 0.75) 0 -1.5em 0 0, rgba(0, 0, 0, 0.75) 1.1em -1.1em 0 0;
+}
+
+/* Animation */
+
+@-webkit-keyframes spinner {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ -moz-transform: rotate(0deg);
+ -ms-transform: rotate(0deg);
+ -o-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(360deg);
+ -moz-transform: rotate(360deg);
+ -ms-transform: rotate(360deg);
+ -o-transform: rotate(360deg);
+ transform: rotate(360deg);
+ }
+}
+@-moz-keyframes spinner {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ -moz-transform: rotate(0deg);
+ -ms-transform: rotate(0deg);
+ -o-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(360deg);
+ -moz-transform: rotate(360deg);
+ -ms-transform: rotate(360deg);
+ -o-transform: rotate(360deg);
+ transform: rotate(360deg);
+ }
+}
+@-o-keyframes spinner {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ -moz-transform: rotate(0deg);
+ -ms-transform: rotate(0deg);
+ -o-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(360deg);
+ -moz-transform: rotate(360deg);
+ -ms-transform: rotate(360deg);
+ -o-transform: rotate(360deg);
+ transform: rotate(360deg);
+ }
+}
+@keyframes spinner {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ -moz-transform: rotate(0deg);
+ -ms-transform: rotate(0deg);
+ -o-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(360deg);
+ -moz-transform: rotate(360deg);
+ -ms-transform: rotate(360deg);
+ -o-transform: rotate(360deg);
+ transform: rotate(360deg);
+ }
+}
+
+.block-sidebar {
+ max-height: 100% !important;
+ overflow: auto !important;
+ padding-top: 90px !important;
+ padding-bottom: 50px !important;
+ position: fixed !important;
+ width: 245px !important;
+}
+
+.inner-control-sidebar {
+ position: fixed;
+ height: auto;
+}
+
+.content-margin-layout {
+ margin: 0px 230px 0px 0px !important;
+ padding: 20px !important;
+}
+
+.admin-content-page {
+ padding: 20px;
+ background: #ecf0f5
+}
+
+.realms {
+ min-height: 554px
+}
+
+.realm-header {
+ clear: both;
+ display:block;
+ display: inline-table;
+ margin: 0 0 10px;
+ line-height: 25px;
+}
+
+.realm-label {
+ float: left;
+ font-size: 16px;
+}
+
+.realm-label label {
+ font-weight: 600 !important;
+}
+
+.realm-choice {
+ right: 0px;
+ position: absolute;
+}
+
+.realm-header .dropdown-menu li a {
+ text-align: left !important;
+ white-space: pre !important;
+ line-height: 7px;
+}
+
+.block-header {
+ position: fixed !important;
+ width: 100% !important;
+ top: 0 !important;
+}
+
+.block-footer {
+ position: fixed !important;
+ width: 100% !important;
+ bottom: 0px !important;
+}
+
+.logo-pos {
+ padding-top: 4px !important;
+ overflow: visible !important;
+}
+
+.angle {
+ border: medium none !important;
+ cursor: pointer;
+ display: inline-table !important;
+ float: right;
+ height: 30px;
+ overflow: hidden;
+ position: relative !important;
+ right: 0;
+ top: -30px;
+ width: 25%;
+ z-index: 3;
+}
+
+.main-header .logo {
+ height: 55px !important;
+}
+
+.w_caption h3 {
+ font-size: 16px;
+}
+
+div.wicket-modal div.w_content_3 {
+ border: 1px solid #eee;
+ border-radius: 20px;
+ padding: 5px;
+}
+
+.tab-content {
+ margin-bottom: 10px;
+ margin-top: 5px;
+ position: relative;
+ overflow-x: hidden;
+ overflow-y: auto;
+ padding: 20px 20px 5px 20px;
+}
+
+.modal-body .tab-content .information {
+ position: relative !important;
+}
+
+.scrollable-tab-content {
+ overflow-y: auto;
+ max-height: 480px;
+}
+
+.inner-scrollable-tab-content {
+ height: 430px;
+ margin-top: 20px;
+ overflow-x: hidden;
+ overflow-y: auto;
+}
+
+a.help {
+ position: relative;
+ display: inline;
+ text-decoration: none;
+}
+
+a.help span {
+ position: absolute;
+ width:19em;
+ color: #000000;
+ background: whitesmoke;
+ visibility: hidden;
+ border-radius: 0px;
+ padding: 3px;
+}
+
+a.help span:after {
+ position: absolute;
+ top: 50%;
+ left: 100%;
+ margin-top: -8px;
+ width: 0;
+ height: 0;
+}
+
+a.help span {
+ visibility: visible;
+ opacity: none;
+ right: 100%;
+ top: 50%;
+ margin-right: 4px;
+ margin-top: -11px;
+ border: 1px solid black;
+ z-index: 1000000;
+}
+
+a.help span a {
+ color: #463;
+ text-decoration: none;
+}
+
+.modal-open .modal {
+ overflow: hidden;
+}
+
+.modal-body {
+ max-height: 550px;
+ overflow-y: auto;
+ overflow-x: hidden;
+}
+
+.modal {
+ background: rgba(0, 0, 0, 0) none repeat scroll 0 0;
+ z-index: 7000 !important;
+}
+
+.wizard-step-title {
+ font-size: 18px !important;
+ font-weight: normal !important;
+ margin-bottom: 10px !important;
+}
+
+div.wizard-view div.wizard-view{
+ max-height: 380px;
+ height: 380px;
+ overflow-y: auto;
+ overflow-x: hidden;
+ padding: 50px 20px 50px 20px;
+}
+
+.wizard-view .wizard-form{
+ max-height: 450px;
+ height: 450px;
+}
+
+.modal-body .tab-content .wizard-view {
+ max-height: 330px !important;
+ height: 330px !important;
+}
+
+.modal-body .tab-content .wizard-form {
+ max-height: 400px !important;
+ height: 400px !important;
+}
+
+.wizard-view > div {
+ display: block;
+ height: 95%;
+ position: relative;
+}
+
+.wizard-view {
+ padding: 0px 5px;
+}
+
+.wizard-form {
+ height:480px;
+ position: relative;
+}
+
+.wizard-form > div {
+ max-height: 440px;
+ height: 440px;
+ overflow-y: auto;
+ overflow-x: hidden;
+ padding: 0px;
+}
+
+.box-body .wizard-form {
+ height:400px !important;
+}
+
+.box-body .wizard-form > div {
+ height: 360px !important;
+}
+
+div.modal-body div.box-body div.wizard-buttons {
+ bottom: 30px;
+}
+
+.wizard-buttons {
+ padding: 10px 0px 5px 0px;
+ position: absolute;
+ bottom: 4px;
+ width: 100%;
+}
+
+.wizard-buttons div.float-left {
+ position: absolute;
+ left: 15px;
+}
+
+.wizard-buttons div.float-right {
+ position: absolute;
+ right: 15px;
+}
+
+.wizard-step-title {
+ font-weight: bold;
+ font-size:medium;
+}
+
+div.realms div.summarize {
+ margin: 50px 100px;
+}
+
+.navbar a {
+ height: 55px
+}
+
+.navbar .footer a {
+ height: 34px
+}
+
+.navbar .user-footer a {
+ height: 34px
+}
+
+span.overridable div.checkbox {
+ float: right;
+ margin: 0px;
+ padding: 0px;
+}
+
+span.overridable div.checkbox label div div.toggle-group label {
+ padding-left: 7px;
+}
+
+div#outer.modal-lg, div#utilityModal.modal-lg, section#notifications .modal-lg {
+ max-width: 1200px;
+ width: 97%;
+}
+
+.details {
+ max-height: 440px;
+ overflow-x: hidden;
+ overflow-y: auto;
+ display: block
+}
+
+th.checkGroupColumn {
+ width: 20px;
+ text-align: center;
+ padding-right: 8px !important;
+}
+
+td.checkGroupColumn {
+ text-align: center;
+}
+
+/**
+ BEGIN - Style for Information panel
+*/
+div.information{
+ margin: 30px 0px 0px 0px;
+ border: 1px solid #EEE;
+ font-size: 10px;
+ color: #888;
+ display: inline-table;
+ width: 100%;
+ clear: both;
+ float:none;
+ position: absolute;
+ bottom: -90px;
+ left: 0px;
+ padding: 2px;
+}
+
+div.infolabel{
+ margin-left: 5px;
+ float:left;
+ width: 150px;
+ font-weight: bold;
+ color: #888;
+}
+
+div.infoleft{
+ float:left;
+ display: inline-table;
+ width: 50%
+}
+
+div.inforight{
+ display: inline-table;
+ width: 50%
+}
+
+div.inforow{
+ display: inline-table;
+ width: 100%
+}
+
+div.wrap{
+ word-wrap: break-word;
+ width: 550px;
+ margin-left: 155px;
+}
+/**
+END - Style for Information panel
+*/
+
+#ownership div.toggle {
+ width: 110px !important;
+}
+
+.table > tbody > tr > td.list_view_panel_labels {
+ vertical-align: middle;
+}
+
+div.searchResult{
+ padding-top: 30px;
+ display: block;
+ clear: both;
+}
+
+.logs .input-group-addon .input-group-btn {
+ width: 130px !important;
+}
+
+.logs .col_width {
+ width: 90% !important;
+}
+
+.logs .box-header {
+ display: none !important;
+}
+
+.logs .box{
+ border-top: 0px !important;
+}
+
+*::after, *::before {
+ box-sizing: border-box;
+}
+
+.wicket-aa-container {
+ border-color: #eee;
+ box-shadow: none;
+ background-clip: padding-box;
+ background-color: #fff;
+ border: 1px solid rgba(0, 0, 0, 0.15);
+ border-radius: 4px;
+ box-shadow: 0 6px 12px rgba(0, 0, 0, 0.176);
+ float: left;
+ font-size: 14px;
+ min-width: 160px;
+ max-height: 250px;
+ z-index: 7001 !important;
+}
+
+div.wicket-aa ul {
+ list-style: none;
+ padding-left: 15px;
+}
+/**
+START - startAt
+*/
+div#startAt {
+ background-color: rgba(98, 98, 98, 0.98) !important;
+ color: #CCC;
+ right: 5px !important;
+ top: 100px !important;
+ min-width: 450px;
+ min-height: 130px !important;
+ z-index: 6000 !important;
+}
+
+div#itemTransformersTogglePanel {
+ min-width: 1000px;
+}
+
+div#startAtContainer {
+ padding: 15px;
+}
+
+div#startAtContainer input {
+ background-color: rgba(200, 200, 200, 0.60) !important;
+}
+/**
+END - startAt
+*/
+
+/**
+START - Notifications
+*/
+/*Temporany fix diagonal stacking*/
+.k-popup.k-notification {
+ box-shadow: none;
+}
+
+.k-notification-error.k-group {
+ background: rgba(100% , 0% , 0% , .7);
+ color: red;
+}
+
+.errorNotification {
+ width: 300px;
+ height: 100px;
+ vertical-align: middle;
+ display: table-cell;
+}
+
+.errorNotification #level {
+ float: left;
+ padding-left: 10px;
+ font-size: 2em;
+ width: 2%;
+}
+
+.errorNotification #message {
+ float: right;
+ padding-left: 0px;
+ width:85%
+}
+
+.k-notification-success.k-group {
+ background: rgba(0% , 60% , 0% , .7);
+ color: #fff;
+}
+
+.successNotification {
+ width: 300px;
+ height: 100px;
+ vertical-align: middle;
+ display: table-cell;
+}
+
+.successNotification #level {
+ float: left;
+ padding-left: 10px;
+ font-size: 2em;
+ width: 2%;
+}
+
+.successNotification #message {
+ float: right;
+ padding-left: 0px;
+ width:85%
+}
+/**
+EN - Notifications
+*/
+
+/**
+START - Actions
+*/
+.actions > li > a {
+ padding: 5px 0px 5px 0px !important;
+}
+
+div.listview-actions a {
+ float:left;
+ padding: 5px 0px 5px 0px !important;
+}
+
+.action a.btn {
+ padding: 0px;
+}
+
+.btn-circle, .circular-actions a {
+ border-radius: 15px !important;
+ font-size: 12px;
+ height: 30px;
+ line-height: 1.42857;
+ padding: 6px 0;
+ text-align: center;
+ width: 30px;
+}
+
+.circular-actions a.btn {
+ background-color: #3c8dbc;
+ border-color: #367fa9;
+ color: #fff;
+}
+
+.btn-circle i, .circular-actions a i {
+ margin: 0px;
+}
+
+.multipanel-btn-minus {
+ padding: 0px 0px 0px 6px;
+ border: 0 none !important;
+}
+
+.multipanel-btn-plus {
+ padding: 15px 0px 8px 6px;
+ border: 0 none !important;
+}
+
+.multipanel-box {
+ padding: 5px;
+ display: inline-table;
+ margin: 0px;
+}
+/**
+END - Actions
+*/
+
+/**
+START - DataTable
+*/
+.dataTable {
+ clear: both;
+}
+/**
+END - DataTable
+*/
+
+/**
+START - Result page
+*/
+.attribute {
+ padding: 0px 4px 0px 4px;
+}
+
+span.highlight .attribute label {
+ color : red;
+}
+/**
+END - Result page
+*/
+
+.navbar-nav > .user-menu > .dropdown-menu > li.user-header {
+ height: auto !important;
+ padding: 10px;
+ text-align: center;
+}
+
+.nav-tabs-custom > .nav-tabs > li.active {
+ border-top-color: #d2d6de !important;
+}
+
+.code-deletion {
+ background-color: #ffdddd;
+ border-color: #f1c0c0;
+}
+
+.code-addition {
+ background-color: #dbffdb;
+ border-color: #c1e9c1;
+}
+
+/**
+START - AjaxDateTimePicker
+*/
+.input-auto-width {
+ width: auto !important;
+}
+
+.icon-top-position {
+ top: 5px !important;
+}
+
+/**
+END - AjaxDateTimePicker
+*/
+
+/**
+START - Search - AjaxDateTimePicker
+*/
+.searchBox .col-xs-12{
+ padding-left: 0px !important;
+ padding-right: 0px !important;
+}
+
+.clause{
+ display: block;
+ line-height: 34px;
+ width: 100%;
+}
+
+.clause .operator{
+ width: 65px !important;
+}
+
+.clause .operator .checkbox{
+ margin: 0px !important;
+}
+
+.clause .field {
+ line-height: 34px;
+ float: left;
+ padding: 0 3px 0px 0px;
+ display: inline-block !important;
+}
+
+.clause .type{
+ width: 170px !important;
+}
+
+.clause .type button{
+ width: 170px !important;
+}
+
+.clause .property{
+ width: 300px;
+}
+
+.clause .property button{
+ width: 300px;
+}
+
+.clause .comparator{
+ width: 100px;
+}
+
+.clause .comparator button{
+ width: 100px !important;
+}
+
+.clause .value{
+ width: 220px;
+}
+
+.clause .date{
+ width: 160px;
+}
+
+.clause .hours{
+ width: 45px;
+}
+
+.clause .separator{
+ width: 20px;
+ padding-left: 12px;
+}
+
+.clause .action{
+ float: left;
+ padding: 0px 7px 0px;
+}
+
+.searchBox .input-group-addon:last-child{
+ border: 1px solid #ccc !important;
+}
+
+.searchBox .input-group{
+ margin-top: 1px;
+}
+
+.custom-autocomplete-box li.selected {
+ background-color: #eee;
+}
+
+/**
+END - Search - AjaxDateTimePicker
+*/
+/**
+START - Parameters Details
+*/
+div#parametersForm{
+ min-height: 220px;
+}
+/**
+END - Parameters Details
+*/
+
+li.todoitem a {
+ cursor: default;
+}
+
+.popover{
+ max-width: 100%;
+}
+
+#popover:hover {
+ cursor: pointer;
+}
+
+.popover-content {
+ color: black;
+}
+
+.form-palette {
+ display: inline-block;
+ width: 119%;
+}
+
+.form-group-inline {
+ display: inline-table;
+ width: 100%;
+}
+
+div#userFilter #title{
+ margin: 10px 0 0 8px;
+ font-weight: bold;
+}
+
+div#userFilter #warning{
+ margin: 1px 0 5px 8px;
+ color: #e00000;
+ font-size: 9px;
+}
+
+div#userFilter #check {
+ margin: 1px 0 5px 8px;
+}
+
+.keyColumn {
+ width: 20px;
+}
+
+/**
+START - Alert widget onside menu
+*/
+div.alert-widget > a > .label {
+ font-size: 9px;
+ line-height: 0.9;
+ padding: 2px 3px;
+ position: absolute;
+ margin-left: 10px;
+ text-align: center;
+ top: 0px;
+}
+
+div.alert-widget > a {
+ display: block;
+ position: relative;
+}
+
+div.alert-widget > a > i {
+ position: absolute;
+ top: 9px;
+}
+
+div.alert-widget{
+ text-align: center;
+ vertical-align: middle;
+ padding-right: 20px;
+}
+
+div.alert-widget .dropdown-menu > li.header {
+ background-color: #ffffff;
+ border-bottom: 1px solid #f4f4f4;
+ border-radius: 4px 4px 0 0;
+ color: #444444;
+ font-size: 14px;
+ padding: 7px 10px;
+}
+
+div.alert-widget .dropdown-menu > li.footer > a {
+ background-color: #fff;
+ border-radius: 0 0 4px 4px;
+ color: #444 !important;
+ font-size: 12px;
+ padding: 7px 10px;
+ text-align: center;
+}
+
+div.alert-widget .dropdown-menu > li .menu {
+ list-style: outside none none;
+ padding: 10px;
+}
+/**
+END - Alert widget onside menu
+*/
+
+/**
+START - Transformers toggle panel
+*/
+div.transformersTogglePanel {
+ background-color: rgba(140, 140, 140, 0.99) !important;
+ width: 1000px !important;
+}
+
+div.transformersContainer {
+ padding: 15px;
+}
+
+div.transformersContainer input {
+ background-color: rgba(200, 200, 200, 0.60) !important;
+}
+
+div.transformersContainer #footer {
+ clear: both;
+ display: block;
+ text-align: right;
+ margin-top: 10px;
+}
+
+div.transformersContainer #body {
+ clear: both;
+ display: block;
+}
+
+div.itemTransformersContainer #body select {
+ border: 1px solid #ccc !important;
+ background: rgba(240, 240, 240, 0.95) !important
+}
+
+div.itemTransformersContainer #body a {
+ color: #ccc !important;
+ cursor: pointer !important;
+}
+
+div#jexlTransformersTogglePanel {
+ right: 400px;
+}
+/**
+END - Transformers toggle panel
+*/
+
+/**
+START - CRONTAB
+*/
+div#schedule input, div#schedule fieldset {
+ width: 50px;
+ float: left
+}
+
+div#templates {
+ padding-top: 30px;
+ clear: both;
+}
+/**
+END - CRONTAB
+*/
+
+/**
+START - EVENTS
+*/
+.events {
+ display: table-row;
+ width: 990px;
+}
+
+.selectedEvents {
+ display: inline-block;
+ height: 100px;
+ margin: 10px 10px 0 10px;
+ overflow-y: auto;
+}
+
+.eventSelection {
+ display: inline-table;
+ float: right;
+ width: 380px;
+ min-width: 530px;
+}
+
+.eventSelection div#value {
+ height: auto;
+ overflow: hidden;
+}
+
+.eventSelection div#value div#custom {
+ width: auto;
+ overflow: hidden;
+}
+
+.eventSelection div#value div#customActions {
+ width: 85px;
+ float: right;
+}
+
+div#selectionContainer select {
+ width: 585px;
+ min-width: 585px;
+}
+/**
+END - EVENTS
+*/
+
+fieldset.input-group {
+ width: 100%;
+}
+
+div.modal-content > div.modal-header {
+ background-color: #f0f0f0;
+ height: 64px;
+}
+
+div.modal-content > div.modal-footer {
+ background-color: #f0f0f0;
+ height: 64px;
+}
+
+.modal-body .box-body div.background-footer {
+ display: none !important;
+}
+
+div.background-footer {
+ background-color: #f0f0f0;
+ display: block;
+ height: 64px;
+ margin-bottom: -15px;
+ margin-left: -30px;
+ margin-top: -25px;
+ width: 1300px;
+}
+
+.logviewer-btn {
+ padding: 0px 16px 20px 0px;
+ float: right;
+}
+
+div#editUserChangePassword > label {
+ color: #e00000;
+}
+
+div > li {
+ list-style-type: none;
+}
+
+th ul.menu, div#inline-actions ul.menu, div#tablehandling ul.menu, div.listview-actions ul.menu {
+ list-style-type: none;
+ margin: 0;
+ padding: 0;
+}
+
+div#tablehandling ul.menu{
+ float: right;
+}
+
+th ul.menu li, div#inline-actions ul.menu li, div#tablehandling ul.menu li, div.listview-actions ul.menu li {
+ display: inline-block;
+}
+
+th ul.menu li a, div#inline-actions ul.menu li a, div.listview-actions ul.menu li a, div#tablehandling ul.menu li a {
+ margin-left: 5px;
+ display: inline-block !important;
+}
+
+ul.menu li a {
+ display: block;
+ cursor: pointer !important;
+}
+
+ul.menu i {
+ width: 35px;
+}
+
+div#inline-actions ul.menu i, div#tablehandling ul.menu i {
+ width: auto !important;
+}
+
+.toggle-menu ul.menu li a {
+ padding: 0px;
+ text-align: left;
+}
+
+div#tablehandling ul.menu li a {
+ padding: 0px !important;
+}
+
+.realm-choice #realm-choice-field {
+ width: 200px;
+ padding-right: 20px;
+}
+
+.realm-choice #realm-choice-folder {
+ color: #3c8dbc;
+}
+
+.palette-scrollbar {
+ min-width: 100%;
+ overflow: scroll;
+}
+
+@-moz-document url-prefix(''){
+ .palette-scrollbar {
+ min-width: 100%;
+ width: auto;
+ overflow: scroll;
+ }
+}
+
+.widget-user-username-panel {
+ display: inline-block;
+ margin-left: 15px;
+}
+
+.widget-user-username-icon {
+ font-size: 32px;
+}
+
+/* User Requests
+============================================================================= */
+
+h4.card-title {
+ text-align: center;
+}
+.bpmn-process-span{
+ display: inline-block;
+ width: 80%;
+}
+
+/* Extensions
+============================================================================= */
+.subnav li a .fa{
+ width: 20px;
+}
+
+
+.sidebar-mini.sidebar-collapse .sidebar-menu .subnav li a span {
+ display: none !important;
+}
+
+
+/* Status Icon
+============================================================================= */
+
+.checkmark_circle_ok {
+ stroke-dasharray: 166;
+ stroke-dashoffset: 166;
+ stroke-width: 2;
+ stroke-miterlimit: 10;
+ stroke: #7ac142;
+ fill: none;
+ animation: stroke 0.6s cubic-bezier(0.65, 0, 0.45, 1) forwards;
+}
+
+.checkmark_circle_error {
+ stroke-dasharray: 166;
+ stroke-dashoffset: 166;
+ stroke-width: 2;
+ stroke-miterlimit: 10;
+ stroke: #FF0000;
+ fill: none;
+ animation: stroke 0.6s cubic-bezier(0.65, 0, 0.45, 1) forwards;
+}
+
+.checkmark_ok {
+ width: 56px;
+ height: 56px;
+ border-radius: 50%;
+ display: block;
+ stroke-width: 2;
+ stroke: #fff;
+ stroke-miterlimit: 10;
+ margin: 10% auto;
+ box-shadow: inset 0px 0px 0px #7ac142;
+ animation: fill_ok .4s ease-in-out .4s forwards, scale .3s ease-in-out .9s both;
+}
+
+.checkmark_error {
+ width: 56px;
+ height: 56px;
+ border-radius: 50%;
+ display: block;
+ stroke-width: 2;
+ stroke: #fff;
+ stroke-miterlimit: 10;
+ margin: 10% auto;
+ box-shadow: inset 0px 0px 0px #FF0000;
+ animation: fill_error .4s ease-in-out .4s forwards, scale .3s ease-in-out .9s both;
+}
+
+.checkmark_check_ok .checkmark_check_error {
+ transform-origin: 50% 50%;
+ stroke-dasharray: 48;
+ stroke-dashoffset: 48;
+ animation: stroke 0.3s cubic-bezier(0.65, 0, 0.45, 1) 0.8s forwards;
+}
+
+.formcard, .card-hover-shadow:hover{
+ box-shadow:0 4px 10px 0 rgba(0,0,0,0.2),0 4px 20px 0 rgba(0,0,0,0.19);
+ margin-bottom: 15px;
+ padding: 0px !important;
+}
+
+.box {
+ position: relative;
+ border-radius: 3px;
+ background: #ffffff;
+ border-top: 3px solid #d2d6de;
+ margin-bottom: 20px;
+ width: 100%;
+ box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
+}
+
+.no-border-top {
+ border-top: 0px !important;
+}
+
+.card-hover-blue:hover{
+ color:#fff!important;
+ background-color:#dd4b39!important
+}
+
+.card-container,.card-panel{
+ padding:0.01em 16px;
+}
+
+.card-container-body{
+ padding:1.01em 16px;
+}
+
+.card-container-body-request{
+ padding-bottom: 45px;
+}
+
+.card-container-padding{
+ padding-bottom: 45px;
+}
+
+.card-font-color a a:hover, a:active, a:focus {
+ color: #ffffff;
+}
+
+.card-panel{
+ margin-top:16px;
+ margin-bottom:16px
+}
+
+.paginator a {
+ color: #999;
+ float: left;
+ padding: 8px 16px;
+ text-decoration: none;
+ transition: background-color .3s;
+ border: 1px solid #ddd;
+}
+
+.paginator a.active {
+ background-color: #4CAF50;
+ color: white;
+ border: 1px solid #4CAF50;
+}
+
+.paginator a:hover:not(.active) {background-color: #ddd;}
+
+@keyframes stroke {
+ 100% {
+ stroke-dashoffset: 0;
+ }
+}
+@keyframes scale {
+ 0%, 100% {
+ transform: none;
+ }
+ 50% {
+ transform: scale3d(1.1, 1.1, 1);
+ }
+}
+@keyframes fill_ok {
+ 100% {
+ box-shadow: inset 0px 0px 0px 30px #7ac142;
+ }
+}
+
+@keyframes fill_error {
+ 100% {
+ box-shadow: inset 0px 0px 0px 30px #FF0000;
+ }
+}
+
+.card-header-style {
+ font-weight: bold !important;
+ font-size: 18px;
+ color: white !important;
+ padding-top: 5px;
+}
+
+.brand-custom{
+ height: 56px;
+ z-index: 1;
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 50%;
+}
+
diff --git a/client/idrepo/enduser/src/main/resources/META-INF/resources/js/accessibility.js b/client/idrepo/enduser/src/main/resources/META-INF/resources/js/accessibility.js
new file mode 100644
index 0000000..b10a48e
--- /dev/null
+++ b/client/idrepo/enduser/src/main/resources/META-INF/resources/js/accessibility.js
@@ -0,0 +1,228 @@
+/*
+ * 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.
+ */
+
+$(document).ready(function () {
+
+ var locationDomain = window.location.origin + '/' + window.location.pathname.split('/')[1];
+
+ var initAssetsManager = function () {
+ var AssetsManager = {};
+
+ var createLink = function (id, url) {
+ if (!$('link#' + id).length && !$('link[href="' + url + '"').length) {
+ var link = document.createElement('link');
+ link.rel = 'stylesheet';
+ link.href = url;
+ link.type = "text/css";
+ $('head').append(link);
+ }
+ };
+
+ var createScript = function (id, url) {
+ if (!$('script#' + id).length && !$('script[src="' + url + '"').length) {
+ var script = document.createElement('script');
+ script.src = url;
+ $('body').append(script);
+ }
+ };
+
+ AssetsManager.checkAlreadyLoaded = function (url, type) {
+ var elems = (type === 'css') ? document.styleSheets : ((type === 'js') ? document.scripts : '');
+ var attr = (type === 'js') ? 'src' : ((type === 'css') ? 'href' : 'none');
+ for (var i in elems) {
+ var attrUrl = elems[i][attr] || "";
+ var assetName = attrUrl.split("/").slice(-1).join();
+ if (attrUrl !== ""
+ && (assetName === url.split("/").slice(-1).join() || assetName === url)) {
+ return true;
+ }
+ }
+ return false;
+ };
+
+ var removeLoaded = function (url, type) {
+ var tag = (type === 'js') ? 'script' : ((type === 'css') ? 'link' : '');
+ if (AssetsManager.checkAlreadyLoaded(url, type)) {
+ $(tag + '[href~="' + url + '"]').remove();
+ }
+ };
+
+ AssetsManager.inject = function (id, url, type) {
+ switch (type) {
+ case 'js':
+ createScript(id, url);
+ break;
+
+ case 'css':
+ createLink(id, url);
+ break;
+
+ default:
+ break;
+ }
+ };
+
+ AssetsManager.remove = function (url, type) {
+ removeLoaded(url, type);
+ };
+
+ return AssetsManager;
+ };
+
+ var initAccessibilityController = function () {
+ AccessibilityController = {};
+
+ var AssetsManager = initAssetsManager();
+
+ var fontSizeFiles = [
+ locationDomain + '/css/accessibility/accessibilityFont.css'
+ ];
+
+ var darkThemeFiles = [
+ locationDomain + '/css/AdminLTE_skins/skin-blue.css',
+ locationDomain + '/css/accessibility/accessibilityHC.css'
+ ];
+
+ var darkThemeMainClass = 'skin-blue';
+ var defaultThemeMainClass = 'skin-green-light';
+
+ var doSwitch = function (check, files) {
+ if (!check) {
+ for (var i = 0; i < files.length; i++) {
+ AssetsManager.remove(files[i], 'css');
+ }
+ } else {
+ for (var i = 0; i < files.length; i++) {
+ AssetsManager.inject('theme_css_' + i, files[i], 'css');
+ }
+ }
+ };
+
+ var doSwitchTheme = function (check, files) {
+ doSwitch(check, files);
+
+ if ($('body').hasClass(defaultThemeMainClass) && check) {
+ $('body').removeClass(defaultThemeMainClass).addClass(darkThemeMainClass);
+ } else {
+ $('body').removeClass(darkThemeMainClass).addClass(defaultThemeMainClass);
+ }
+ };
+
+ var savePreference = function (key, value) {
+ window.localStorage.setItem(key, value);
+ };
+
+ var getPreference = function (key) {
+ var storageValue = window.localStorage.getItem(key);
+ if (storageValue === null) {
+ savePreference(key, 'false');
+ }
+ return storageValue === 'true';
+ };
+
+ AccessibilityController.FONT_SIZE_PREF = 'font_size_pref';
+ AccessibilityController.HC_THEME_PREF = 'hc_theme_pref';
+
+ var isIncreasedFont = getPreference(AccessibilityController.FONT_SIZE_PREF);
+ var isHighContrast = getPreference(AccessibilityController.HC_THEME_PREF);
+
+ AccessibilityController.checkPref = function (pref) {
+ switch (pref) {
+ case AccessibilityController.FONT_SIZE_PREF:
+ doSwitch(isIncreasedFont, fontSizeFiles);
+ break;
+
+ case AccessibilityController.HC_THEME_PREF:
+ doSwitchTheme(isHighContrast, darkThemeFiles);
+ break;
+
+ default:
+ break;
+ }
+ };
+
+ AccessibilityController.switchIncreasedFont = function () {
+ isIncreasedFont = !isIncreasedFont;
+ doSwitch(isIncreasedFont, fontSizeFiles);
+ savePreference(AccessibilityController.FONT_SIZE_PREF, isIncreasedFont);
+ };
+
+ AccessibilityController.switchTheme = function () {
+ isHighContrast = !isHighContrast;
+ doSwitchTheme(isHighContrast, darkThemeFiles);
+ savePreference(AccessibilityController.HC_THEME_PREF, isHighContrast);
+ };
+
+ return AccessibilityController;
+ };
+
+ var AccessibilityController = initAccessibilityController();
+
+ AccessibilityController.checkPref(AccessibilityController.FONT_SIZE_PREF);
+ AccessibilityController.checkPref(AccessibilityController.HC_THEME_PREF);
+
+ $('#change_contrast').off('click.acc_hc');
+ $('#change_contrast').on('click.acc_hc', function () {
+ AccessibilityController.switchTheme();
+ return false;
+ });
+
+ $('#change_contrast').off('keydown.key_acc_hc keypress.key_acc_hc');
+ $('#change_contrast').on('keydown.key_acc_hc keypress.key_acc_hc', function (event) {
+ // check "enter" key pressed
+ if (event.which === 13) {
+ AccessibilityController.switchTheme();
+
+ event.preventDefault();
+ return false;
+ }
+ });
+
+ $('#change_fontSize').off('click.acc_f');
+ $('#change_fontSize').on('click.acc_f', function () {
+ AccessibilityController.switchIncreasedFont();
+ return false;
+ });
+
+ $('#change_fontSize').off('keydown.key_acc_f keypress.key_acc_f');
+ $('#change_fontSize').on('keydown.key_acc_f keypress.key_acc_f', function (event) {
+ // check "enter" key pressed
+ if (event.which === 13) {
+ AccessibilityController.switchIncreasedFont();
+
+ event.preventDefault();
+ return false;
+ }
+ });
+
+ $('body').off('keydown.acc_binding keypress.acc_binding');
+ $('body').on('keydown.acc_binding keypress.acc_binding', function (event) {
+ // alt - shift - F
+ // alt - shift - H
+ if (event.altKey && event.shiftKey) {
+ if (event.keyCode === 72) {
+ AccessibilityController.switchTheme();
+ } else if (event.keyCode === 70) {
+ AccessibilityController.switchIncreasedFont();
+ }
+ event.preventDefault();
+ }
+ });
+
+});
diff --git a/client/idrepo/enduser/src/main/resources/META-INF/resources/js/copyToClipboard.js b/client/idrepo/enduser/src/main/resources/META-INF/resources/js/copyToClipboard.js
new file mode 100644
index 0000000..f4618a6
--- /dev/null
+++ b/client/idrepo/enduser/src/main/resources/META-INF/resources/js/copyToClipboard.js
@@ -0,0 +1,79 @@
+/*
+ * 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.
+ */
+
+if (typeof copyToClipboard === 'undefined') {
+ copyToClipboard = function (element, tag_value_to_copy, fake_textarea_ID, feedback_selector) {
+ var $elem = $(element);
+
+ // creating new textarea element and giveing it an ID
+ var temp = document.createElement('textarea');
+ temp.id = fake_textarea_ID;
+ temp.style.display = 'block';
+
+ // Make less noise in the page
+ temp.style.height = 0;
+
+ // Append it to the page somewhere, in this case <body>
+ $elem.append(temp);
+
+ // Copy whatever is in the div to our new textarea
+ temp.value = $elem.attr(tag_value_to_copy);
+ $(temp).text(temp.value);
+
+ // Copy whatever inside the textarea to clipboard
+ $(temp).focus().select();
+ document.execCommand('SelectAll');
+ document.execCommand("copy", false, null);
+
+ if ($.browser.mozilla && !$.browser.chrome) {
+ try {
+ var range = document.createRange();
+ range.selectNodeContents(temp);
+ var selection = window.getSelection();
+ selection.removeAllRanges();
+ selection.addRange(range);
+
+ document.execCommand("Copy", false, null);
+ } catch (e) {
+ }
+ }
+
+ // Remove the textarea
+ $(temp).remove();
+
+ $elem.siblings(feedback_selector).fadeIn();
+
+ // Remove feedback element
+ window.setTimeout(function () {
+ $elem.siblings(feedback_selector).fadeOut();
+ }, 1000);
+ };
+
+ function doCopyToClipboard(el) {
+ var feedback_selector = '.copy-clipboard-feedback';
+ var fake_textarea_selector = 'tttt';
+ var tag_value_to_copy = 'data-value';
+
+ if (!$(feedback_selector + ":visible").length) {
+ copyToClipboard(el, tag_value_to_copy, fake_textarea_selector, feedback_selector);
+ }
+ }
+}
+
+
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/SelfUpdate.java b/client/idrepo/enduser/src/main/resources/META-INF/resources/js/syncopeEnduser.js
similarity index 70%
copy from client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/SelfUpdate.java
copy to client/idrepo/enduser/src/main/resources/META-INF/resources/js/syncopeEnduser.js
index 7c86c2d..006c9a1 100644
--- a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/SelfUpdate.java
+++ b/client/idrepo/enduser/src/main/resources/META-INF/resources/js/syncopeEnduser.js
@@ -16,16 +16,9 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.syncope.client.enduser.pages;
-import org.apache.wicket.request.mapper.parameter.PageParameters;
-
-public class SelfUpdate extends BaseEnduserWebPage {
-
- private static final long serialVersionUID = 164651008547631054L;
-
- public SelfUpdate(final PageParameters parameters) {
- super(parameters);
- }
-
-}
+$(document).ready(function (){
+ $('.card-header .card-title').on('click', function(){
+ $('.card.card-outline .collapse').css('padding', '2em');
+ });
+});
diff --git a/client/idrepo/enduser/src/main/resources/customFormAttributes.json b/client/idrepo/enduser/src/main/resources/customFormAttributes.json
deleted file mode 100644
index 9e26dfe..0000000
--- a/client/idrepo/enduser/src/main/resources/customFormAttributes.json
+++ /dev/null
@@ -1 +0,0 @@
-{}
\ No newline at end of file
diff --git a/client/idrepo/enduser/src/main/resources/customFormLayout.json b/client/idrepo/enduser/src/main/resources/customFormLayout.json
new file mode 100644
index 0000000..af4f21c
--- /dev/null
+++ b/client/idrepo/enduser/src/main/resources/customFormLayout.json
@@ -0,0 +1,14 @@
+{
+ "formClass": "org.apache.syncope.client.enduser.panels.UserFormPanel",
+ "auxClasses": true,
+ "groups": true,
+ "plainAttrs": true,
+ "derAttrs": true,
+ "virAttrs": true,
+ "resources": true,
+ "whichPlainAttrs": {},
+ "whichDerAttrs": {},
+ "whichVirAttrs": {},
+ "passwordManagement": true,
+ "detailsManagement": true
+}
diff --git a/client/idrepo/enduser/src/main/resources/enduser.properties b/client/idrepo/enduser/src/main/resources/enduser.properties
index 1d62418..b4061af 100644
--- a/client/idrepo/enduser/src/main/resources/enduser.properties
+++ b/client/idrepo/enduser/src/main/resources/enduser.properties
@@ -26,6 +26,15 @@
captcha=true
csrf=true
+# Sidebar
+sidebar=org.apache.syncope.client.enduser.panels.Sidebar
+
+# Page
+page.profile=org.apache.syncope.client.enduser.pages.Dashboard
+page.edituser=org.apache.syncope.client.enduser.pages.EditUser
+page.editchangepassword=org.apache.syncope.client.enduser.pages.EditChangePassword
+page.editsecurityquestion=org.apache.syncope.client.enduser.pages.EditSecurityQuestion
+
security.headers.X-XSS-Protection=1; mode=block
security.headers.Strict-Transport-Security=max-age=31536000; includeSubDomains; preload
security.headers.X-Content-Type-Options=nosniff
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses_ru.properties b/client/idrepo/enduser/src/main/resources/oidcclient-agent.properties
similarity index 80%
copy from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses_ru.properties
copy to client/idrepo/enduser/src/main/resources/oidcclient-agent.properties
index 7f39171..17775f8 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses_ru.properties
+++ b/client/idrepo/enduser/src/main/resources/oidcclient-agent.properties
@@ -14,5 +14,13 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-#
-auxClasses.palette=\u0412\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043a\u043b\u0430\u0441\u0441\u044b
+conf.directory=${conf.directory}
+
+anonymousUser=${anonymousUser}
+anonymousKey=${anonymousKey}
+
+scheme=https
+host=localhost
+port=8443
+rootPath=/syncope/rest/
+useGZIPCompression=true
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/SyncopeWebApplication.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/SyncopeEnduserApplication.properties
similarity index 81%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/SyncopeWebApplication.properties
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/SyncopeEnduserApplication.properties
index 0c1754b..4a13869 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/SyncopeWebApplication.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/SyncopeEnduserApplication.properties
@@ -73,7 +73,7 @@
implementations=Implementations
timeout=Operation is taking too long: it will be executed in background. Please check later for the result (errors won't be triggered).
-security=Security
+editsecurityquestion=Security question
before=Before
after=After
@@ -81,3 +81,26 @@
invalid.security.answer=Invalid security answer
tooLargeFile=File is too large, max upload file size is ${maxUploadSizeB} bytes (${maxUploadSizeMB} MB).
+home=Home
+profile=Personal Information
+requests=User Requests
+edituser=Edit profile
+submit=Submit
+cancel=Cancel
+editchangepassword=Change password
+attributes.derived=Derived Attributes
+attributes.plain=Plain Attributes
+attributes.virtual=Virtual Attributes
+captcha=Captcha
+details=Details
+user_request_error=Error during user request. Please contact your administrator
+
+page.home=Home
+page.changePassword=Change Password
+page.editSecurityQuestion=Edit Security Question
+page.edituser=Edit User
+page.confirmPasswordReset=Confirm Password Reset
+page.selfPwdReset=Password Reset
+page.selfRegistration=Registration
+page.resultPage=Result Page
+page.userRequests=User Requests
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/SyncopeEnduserApplication_fr_CA.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/SyncopeEnduserApplication_fr_CA.properties
new file mode 100644
index 0000000..59104f0
--- /dev/null
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/SyncopeEnduserApplication_fr_CA.properties
@@ -0,0 +1,105 @@
+#
+# Copyright (C) 2020 Tirasa (info@tirasa.net)
+#
+# Licensed 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.
+#
+users=Utilisateurs
+groups=Groupes
+configuration=Configuration
+resources=Ressources
+connectors=Raccordements
+reports=Rapports
+tasks=T\u00e2ches
+logout=D\u00e9connexion
+schema=Sch\u00e9ma
+operation_succeeded=Op\u00e9ration compl\u00e9t\u00e9e avec succ\u00e8s
+operation_error=Une erreur s'est produite pendant l'op\u00e9ration
+alert=Alerte:
+confirmDelete=Voulez-vous vraiment supprimer le(s) article(s) s\u00e9lectionn\u00e9(s)?
+confirmUnlink=Voulez-vous vraiment supprimer le lien entre le(s) article(s) s\u00e9lectionn\u00e9(s) et la ressource?
+confirmUnassign=Souhaitez-vous vraiment supprimer l'affectation entre le(s) article(s) s\u00e9lectionn\u00e9(s) et la ressource?
+confirmDeprovision=Souhaitez-vous vraiment d\u00e9provisionner le(s) article(s) s\u00e9lectionn\u00e9(s)?
+confirmProvision=Souhaitez-vous vraiment approvisionner le(s) article(s) s\u00e9lectionn\u00e9(s)?
+confirmClone=Voulez-vous vraiment cloner le(s) article(s) s\u00e9lectionn\u00e9(s)?
+
+dropDownChoiceField.nullValid=Faire un choix
+DateTimeField$HoursValidator=La valeur horaire doit \u00eatre dans la gamme (1, 12)
+error=Erreur
+generic_error=Une erreur s'est produite pendant l'op\u00e9ration
+id=Cl\u00e9
+name=Nom
+palette.available=Disponible
+palette.selected=S\u00e9lectionn\u00e9
+jexl_info=Ce champ requiert une expression JEXL, par exemple:
+jexl_ex1=nom de famille + ',' + pr\u00e9nom
+jexl_ex2=new.' + nom de famille
+jexl_syntax_url=R\u00e9f\u00e9rence JEXL compl\u00e8te
+create=Cr\u00e9er
+key=Cl\u00e9
+types=Types
+self-registration-link=Auto-inscription
+self-pwd-reset-link=Mot de passe de r\u00e9initialisation automatique
+user-requests-link=Demandes des utilisateurs
+realms=Domaines
+roles=R\u00f4les
+policies=Politiques
+workflow=Flux
+logs=Registres
+layouts=Dispositions
+notifications=Notifications
+parameters=Param\u00e8tres
+extensions=Extensions
+NavigatorLabel=Affichage des rang\u00e9es ${from} \u00e0 ${to} de ${of}
+displayRows=Rang\u00e9es \u00e0 afficher
+OrderByLink.CSS.ascending=tri_asc
+OrderByLink.CSS.descending=tri_desc
+OrderByLink.CSS.none=tri
+entitlements=Droits et privil\u00e8ges
+audit=Audit
+connectors.confirm.reload=Cette demande est potentiellement dangereuse pour le d\u00e9roulement des op\u00e9rations, continuer?
+intAttrNameInfo.help=En plus des attributs auto-compl\u00e9t\u00e9s, vous pouvez \u00e9galement faire r\u00e9f\u00e9rence \u00e0 des groupes, des objets, des appartenances ou des privil\u00e8ges, par exemple:
+confirmGlobalLogout=Voulez-vous vraiment effectuer une d\u00e9connexion compl\u00e8te?
+implementations=Impl\u00e9mentations
+
+timeout=L'op\u00e9ration prend trop de temps: elle sera ex\u00e9cut\u00e9e en arri\u00e8re-plan. Veuillez v\u00e9rifier plus tard le r\u00e9sultat (les erreurs ne seront pas d\u00e9tect\u00e9es).
+editsecurityquestion=Question de s\u00e9curit\u00e9
+before=Avant
+after=Apr\u00e8s
+
+captcha_error=Le captcha saisi ne correspond pas
+
+invalid.security.answer=R\u00e9ponse de s\u00e9curit\u00e9 non valide
+tooLargeFile=Le fichier est trop grand, la taille du fichier de t\u00e9l\u00e9chargement max est ${maxUploadSizeB} bytes (${maxUploadSizeMB} MB).
+home=Aper\u00e7u
+profile=Information personnelle
+requests=Demandes des utilisateurs
+edituser=Editer le profil
+submit=Soumettre
+cancel=Annuler
+editchangepassword=Changer mot de passe
+attributes.derived=Derived Attributes
+attributes.plain=Editer le profil
+attributes.virtual=Virtual Attributes
+captcha=Captcha
+details=Des d\u00e9tails
+user_request_error=Erreur lors de la demande de l'utilisateur. Veuillez contacter votre administrateur
+
+page.home=Aper\u00e7u
+page.changePassword=Changer mot de passe
+page.editSecurityQuestion=Modifier la question de s\u00e9curit\u00e9
+page.edituser=Modifier l'utilisateur
+page.confirmPasswordReset=Confirm Password Reset
+page.selfPwdReset=Password Reset
+page.selfRegistration=Enregistrement
+page.resultPage=Page de r\u00e9sultat
+page.userRequests=Demandes des utilisateurs
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/SyncopeWebApplication_it.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/SyncopeEnduserApplication_it.properties
similarity index 78%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/SyncopeWebApplication_it.properties
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/SyncopeEnduserApplication_it.properties
index e8620a0..7330ec8 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/SyncopeWebApplication_it.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/SyncopeEnduserApplication_it.properties
@@ -70,7 +70,7 @@
implementations=Implementazioni
timeout=L'operazione sta durando troppo: sar\u00e0 eseguita in background. Verifica il risultato pi\u00f9 tardi (gli errori non saranno notificati).
-security=Sicurezza
+editsecurityquestion=Domanda segreta
before=Prima
after=Dopo
@@ -78,3 +78,29 @@
invalid.security.answer=Risposta di sicurezza non valida
tooLargeFile=File troppo grande, la dimensione massima ammessa \\u00e8 ${maxUploadSizeB} bytes (${maxUploadSizeMB} MB).
+home=Home
+profile=Informazioni personali
+requests=User Requests
+edituser=Modifica profilo
+submit=Submit
+cancel=Cancel
+editchangepassword=Gestione password
+attributes.derived=Derived Attributes
+attributes.plain=Plain Attributes
+attributes.virtual=Virtual Attributes
+captcha=Captcha
+details=Details
+user-requests-link=User Requests
+self-pwd-reset-link=Self Password Reset
+self-registration-link=Self Registration
+user_request_error=Errore durante la richiesta. Si prega di contattare l'amministratore di sistema.
+
+page.home=Home
+page.changePassword=Cambio Password
+page.editSecurityQuestion=Modifica domanda segreta
+page.edituser=Modifica profilo
+page.confirmPasswordReset=Conferma Reset Password
+page.selfPwdReset=Password Reset
+page.selfRegistration=Self Registration
+page.resultPage=Risultato
+page.userRequests=User Requests
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/SyncopeWebApplication_ja.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/SyncopeEnduserApplication_ja.properties
similarity index 83%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/SyncopeWebApplication_ja.properties
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/SyncopeEnduserApplication_ja.properties
index 553dfb9..10e8d09 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/SyncopeWebApplication_ja.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/SyncopeEnduserApplication_ja.properties
@@ -68,10 +68,36 @@
confirmGlobalLogout=\u30b0\u30ed\u30fc\u30d0\u30eb\u30ed\u30b0\u30a2\u30a6\u30c8\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b?
implementations=\u5c0e\u5165
timeout=\u64cd\u4f5c\u306b\u9577\u6642\u9593\u304b\u304b\u3063\u3066\u3044\u307e\u3059\: \u30d0\u30c3\u30af\u30b0\u30e9\u30a6\u30f3\u30c9\u3067\u5b9f\u884c\u3055\u308c\u307e\u3059\u3002 \u7d50\u679c\u3092\u5f8c\u3067\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044 (\u30a8\u30e9\u30fc\u306f\u5f15\u304d\u8d77\u3053\u3057\u307e\u305b\u3093)\u3002
-security=\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3
+editsecurityquestion=\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3
before=\u524d
after=\u5f8c
captcha_error=\u5165\u529b\u3055\u308c\u305f\u30ad\u30e3\u30d7\u30c1\u30e3\u304c\u4e00\u81f4\u3057\u307e\u305b\u3093
invalid.security.answer=Invalid security answer
tooLargeFile=File is too large, max upload file size is ${maxUploadSizeB} bytes (${maxUploadSizeMB} MB).
+home=Home
+profile=Personal Information
+requests=User Requests
+edituser=\u30d7\u30ed\u30d5\u30a1\u30a4\u30eb\u7de8\u96c6
+submit=Submit
+cancel=Cancel
+editchangepassword=Change password
+attributes.derived=Derived Attributes
+attributes.plain=Plain Attributes
+attributes.virtual=Virtual Attributes
+captcha=Captcha
+details=Details
+user-requests-link=User Requests
+self-pwd-reset-link=Self Password Reset
+self-registration-link=Self Registration
+user_request_error=\u30e6\u30fc\u30b6\u30fc\u30ea\u30af\u30a8\u30b9\u30c8\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 \u7ba1\u7406\u8005\u306b\u9023\u7d61\u3057\u3066\u304f\u3060\u3055\u3044
+
+page.home=Home
+page.changePassword=Change Password
+page.editSecurityQuestion=Edit Security Question
+page.edituser=Edit User
+page.confirmPasswordReset=Confirm Password Reset
+page.selfPwdReset=Password Reset
+page.selfRegistration=Registration
+page.resultPage=Result Page
+page.userRequests=User Requests
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/SyncopeWebApplication_pt_BR.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/SyncopeEnduserApplication_pt_BR.properties
similarity index 79%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/SyncopeWebApplication_pt_BR.properties
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/SyncopeEnduserApplication_pt_BR.properties
index d1d66c5..9223e0b 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/SyncopeWebApplication_pt_BR.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/SyncopeEnduserApplication_pt_BR.properties
@@ -70,10 +70,36 @@
implementations=Implementa\u00e7\u00f5es
timeout=Operation is taking too long: it will be executed in background. Please check later for the result (errors won't be triggered).
-security=Security
+editsecurityquestion=Security question
before=Before
after=After
captcha_error=Captcha entered does not match
invalid.security.answer=Invalid security answer
tooLargeFile=File is too large, max upload file size is ${maxUploadSizeB} bytes (${maxUploadSizeMB} MB).
+home=Home
+profile=Personal Information
+requests=User Requests
+edituser=Edit profile
+submit=Submit
+cancel=Cancel
+editchangepassword=Change password
+attributes.derived=Derived Attributes
+attributes.plain=Plain Attributes
+attributes.virtual=Virtual Attributes
+captcha=Captcha
+details=Details
+user-requests-link=User Requests
+self-pwd-reset-link=Self Password Reset
+self-registration-link=Self Registration
+user_request_error=Erro durante a solicita\u00e7\u00e3o do usu\u00e1rio. Por favor contacte o seu administrador
+
+page.home=Home
+page.changePassword=Change Password
+page.editSecurityQuestion=Edit Security Question
+page.edituser=Edit User
+page.confirmPasswordReset=Confirm Password Reset
+page.selfPwdReset=Password Reset
+page.selfRegistration=Registration
+page.resultPage=Result Page
+page.userRequests=User Requests
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/SyncopeWebApplication_ru.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/SyncopeEnduserApplication_ru.properties
similarity index 87%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/SyncopeWebApplication_ru.properties
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/SyncopeEnduserApplication_ru.properties
index a1859f5..ecf3ec7 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/SyncopeWebApplication_ru.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/SyncopeEnduserApplication_ru.properties
@@ -69,10 +69,36 @@
implementations=\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438
timeout=Operation is taking too long: it will be executed in background. Please check later for the result (errors won't be triggered).
-security=Security
+editsecurityquestion=Security question
before=Before
after=After
captcha_error=Captcha entered does not match
invalid.security.answer=Invalid security answer
tooLargeFile=File is too large, max upload file size is ${maxUploadSizeB} bytes (${maxUploadSizeMB} MB).
+home=Home
+profile=Personal Information
+requests=User Requests
+edituser=\u0420\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0444\u0438\u043b\u044c
+submit=Submit
+cancel=Cancel
+editchangepassword=Change password
+attributes.derived=Derived Attributes
+attributes.plain=Plain Attributes
+attributes.virtual=Virtual Attributes
+captcha=Captcha
+details=Details
+user-requests-link=User Requests
+self-pwd-reset-link=Self Password Reset
+self-registration-link=Self Registration
+user_request_error=\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435\u0441\u044c \u043a \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0443
+
+page.home=Home
+page.changePassword=Change Password
+page.editSecurityQuestion=Edit Security Question
+page.edituser=Edit User
+page.confirmPasswordReset=Confirm Password Reset
+page.selfPwdReset=Password Reset
+page.selfRegistration=Registration
+page.resultPage=Result Page
+page.userRequests=User Requests
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/markup/html/form/BinaryFieldPanel.html b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/markup/html/form/BinaryFieldPanel.html
index 4037265..e39dcc5 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/markup/html/form/BinaryFieldPanel.html
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/markup/html/form/BinaryFieldPanel.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
@@ -36,8 +37,8 @@
</span>
<input wicket:id="fileUpload" type="file"/>
<div>
- <a href="#" wicket:id="downloadLink"><i title="download" alt="file download icon" class="far fa-arrow-alt-circle-down"></i></a>
- <a href="#" wicket:id="resetLink"><i title="remove value" alt="remove value icon" class="fas fa-times"></i></a>
+ <a href="#" wicket:id="downloadLink"><i title="download" alt="file download icon" class="fa fa-arrow-alt-circle-down"></i></a>
+ <a href="#" wicket:id="resetLink"><i title="remove value" alt="remove value icon" class="fa fa-times"></i></a>
<span wicket:id="preview"/>
</div>
</form>
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/markup/html/form/MultiFieldPanel.html b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/markup/html/form/MultiFieldPanel.html
index 6bcb727..1f645f2 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/markup/html/form/MultiFieldPanel.html
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/markup/html/form/MultiFieldPanel.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/markup/html/form/MultiFieldPanel_ru.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/markup/html/form/MultiFieldPanel_ru.properties
deleted file mode 100644
index 3971914..0000000
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/markup/html/form/MultiFieldPanel_ru.properties
+++ /dev/null
@@ -1,29 +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.
-#
-# minLength=Минимальный размер пароля
-minLength=\u041c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u0440\u0430\u0437\u043c\u0435\u0440 \u043f\u0430\u0440\u043e\u043b\u044f
-# maxLength=Максимальный размер пароля
-maxLength=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u0440\u0430\u0437\u043c\u0435\u0440 \u043f\u0430\u0440\u043e\u043b\u044f
-# historyLength=Размер истории паролей
-historyLength=\u0420\u0430\u0437\u043c\u0435\u0440 \u0438\u0441\u0442\u043e\u0440\u0438\u0438 \u043f\u0430\u0440\u043e\u043b\u0435\u0439
-# digitRequired=Пароль должен содержать не менее одной цифры
-digitRequired=\u041f\u0430\u0440\u043e\u043b\u044c \u0434\u043e\u043b\u0436\u0435\u043d \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u043d\u0435 \u043c\u0435\u043d\u0435\u0435 \u043e\u0434\u043d\u043e\u0439 \u0446\u0438\u0444\u0440\u044b
-# prefixesNotPermitted=Пароль не должен содержать префикс
-prefixesNotPermitted=\u041f\u0430\u0440\u043e\u043b\u044c \u043d\u0435 \u0434\u043e\u043b\u0436\u0435\u043d \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u043f\u0440\u0435\u0444\u0438\u043a\u0441
-# apply=Сохранить
-apply=\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/navigation/Navbar.html b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/navigation/Navbar.html
index f633396..9a177f8 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/navigation/Navbar.html
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/navigation/Navbar.html
@@ -83,7 +83,7 @@
<div id="logout" class="btn-navbar-right">
<i aria-label="Logout" tabindex="0" accesskey="H"
- class="fas fa-sign-out-alt">
+ class="fa fa-sign-out-alt">
</i>
</div>
</a>
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/BaseEnduserWebPage.html b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/BaseEnduserWebPage.html
deleted file mode 100644
index 5d44a8e..0000000
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/BaseEnduserWebPage.html
+++ /dev/null
@@ -1,57 +0,0 @@
-<!DOCTYPE html>
-<!--
-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.
--->
-<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
- <head>
- <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
- <meta charset="UTF-8"/>
- <meta content='width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no' name='viewport'/>
-
- <title>Apache Syncope</title>
-
- <link rel="shortcut icon" href="ui-commons/img/favicon.png" type="image/png"/>
-
- <link href="webjars/font-awesome/${font-awesome.version}/css/all.min.css" rel="stylesheet" type="text/css"/>
- <link href="webjars/ionicons/${ionicons.version}/css/ionicons.min.css" rel="stylesheet" type="text/css" />
- <link href="ui-commons/css/fonts.css" rel="stylesheet" type="text/css"/>
-
- <link href="ui-commons/css/animations.css" rel="stylesheet" type="text/css" />
- <link href="ui-commons/css/syncopeUI.css" rel="stylesheet" type="text/css"/>
- <link href="ui-commons/css/login.css" rel="stylesheet" type="text/css" />
-
- <!-- accessibility -->
- <script type="text/javascript" src="ui-commons/js/accessibility.js"></script>
-
- <script type="text/javascript" src="webjars/bootbox/${bootbox.version}/bootbox.js"></script>
- <script type="text/javascript" src="webjars/jQuery-slimScroll/${jquery-slimscroll.version}/jquery.slimscroll.min.js"></script>
- </head>
- <body wicket:id="body" class="skin-green-light hold-transition sidebar-mini">
- <span wicket:id="navbar">[NAVBAR]</span>
-
- <div class="wrapper">
- <span wicket:id="feedback"></span>
-
- <div class="content-wrapper custom_content_wrapper">
- <wicket:child/>
- </div>
- </div>
-
- <div id="veil">Loading...</div>
- </body>
-</html>
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/BasePage.html b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/BasePage.html
new file mode 100644
index 0000000..b03dfbd
--- /dev/null
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/BasePage.html
@@ -0,0 +1,90 @@
+<!DOCTYPE html>
+<!--
+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.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org" wicket:message="lang:lang">
+<head>
+ <meta charset="UTF-8"/>
+ <meta content="width=device-width, initial-scale=1" name="viewport"/>
+
+ <title>Apache Syncope</title>
+
+ <link rel="shortcut icon" href="ui-commons/img/favicon.png" type="image/png"/>
+
+ <link href="webjars/font-awesome/${font-awesome.version}/css/all.min.css" rel="stylesheet" type="text/css"/>
+ <link href="webjars/ionicons/${ionicons.version}/css/ionicons.min.css" rel="stylesheet" type="text/css"/>
+ <link href="ui-commons/css/fonts.css" rel="stylesheet" type="text/css"/>
+
+ <link href="css/AdminLTE_plugins/dataTables.bootstrap4.min.css" rel="stylesheet" type="text/css"/>
+ <link href="ui-commons/css/animations.css" rel="stylesheet" type="text/css"/>
+ <link href="ui-commons/css/syncopeUI.css" rel="stylesheet" type="text/css"/>
+ <link href="css/syncopeEnduser.css" rel="stylesheet" type="text/css"/>
+
+ <!-- accessibility -->
+ <link href="ui-commons/css/accessibility.css" rel="stylesheet" type="text/css" />
+ <script type="text/javascript" src="ui-commons/js/accessibility.js"></script>
+
+ <script type="text/javascript" src="webjars/bootbox/${bootbox.version}/bootbox.js"></script>
+ <script type="text/javascript" src="webjars/jQuery-slimScroll/${jquery-slimscroll.version}/jquery.slimscroll.min.js"></script>
+ <script type="text/javascript">
+ // global variable for IndicatingOnConfirmAjaxLink
+ var proceed = false;
+ </script>
+</head>
+<body class="hold-transition sidebar-mini" wicket:id="body">
+
+<div class="wrapper">
+ <span wicket:id="feedback"></span>
+ <nav class="main-header navbar navbar-expand navbar-red navbar-light" aria-label="primary" style="z-index: 0">
+ <ul class="navbar-nav">
+ <li class="nav-item">
+ <a href="#" class="nav-link" data-widget="pushmenu" role="button" wicket:id="collapse">
+ <i class="fas fa-bars"></i>
+ </a>
+ </li>
+ </ul>
+
+ <ul class="navbar-nav ml-auto">
+ <li class="nav-item">
+ <a class="nav-link" href="#" wicket:id="logout">
+ <i class="fas fa-sign-out-alt" aria-hidden="true"></i>
+ </a>
+ </li>
+ </ul>
+ </nav>
+ <aside wicket:id="sidebar" class="main-sidebar sidebar-light-red elevation-4" aria-label="secondary">[SIDEBAR]</aside>
+
+ <div class="content-wrapper" wicket:id="contentWrapper" role="main">
+ <section class="content-header">
+ <h1><span wicket:id="pageTitle"/></h1>
+ </section>
+ <wicket:child/>
+ </div>
+
+ <footer class="main-footer">
+ <strong>Copyright © 2010-${year}
+ <a href="http://www.apache.org/" target="_blank" rel="noopener noreferrer">The Apache Software Foundation</a>.</strong>
+ All rights reserved.
+ </footer>
+
+ <div class="control-sidebar-bg" style="position: fixed; height: auto;"></div>
+</div>
+
+<div id="veil">Loading...</div>
+</body>
+</html>
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses_ru.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/BasePage.properties
similarity index 82%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses_ru.properties
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/BasePage.properties
index 7f39171..8a6ebdb 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses_ru.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/BasePage.properties
@@ -14,5 +14,13 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-#
-auxClasses.palette=\u0412\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043a\u043b\u0430\u0441\u0441\u044b
+home=Home
+version=Version
+domain=Domain
+
+systemInfo=System Information
+hostname=Host Name
+processors=Available Processors
+os=Operating System
+jvm=JVM
+lang=en
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses_ru.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/BasePage_fr_CA.properties
similarity index 79%
copy from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses_ru.properties
copy to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/BasePage_fr_CA.properties
index 7f39171..d39be37 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses_ru.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/BasePage_fr_CA.properties
@@ -14,5 +14,12 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-#
-auxClasses.palette=\u0412\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043a\u043b\u0430\u0441\u0441\u044b
+home=Accueil
+version=Version
+domain=Domaine
+systemInfo=Information sur le syst\u00e8me
+hostname=Nom d'h\u00f4te
+processors=Processeurs disponibles
+os=Syst\u00e8me d'exploitation
+jvm=JVM
+lang=fr
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses_ru.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/BasePage_it.properties
similarity index 81%
copy from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses_ru.properties
copy to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/BasePage_it.properties
index 7f39171..660159f 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses_ru.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/BasePage_it.properties
@@ -14,5 +14,13 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-#
-auxClasses.palette=\u0412\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043a\u043b\u0430\u0441\u0441\u044b
+home=Home
+version=Versione
+domain=Dom\u00ednio
+
+systemInfo=Informazioni di Sistema
+hostname=Nome Host
+processors=Processori Disponibili
+os=Sistema Operativo
+jvm=JVM
+lang=it
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/BasePage_ja.properties
similarity index 69%
copy from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel.properties
copy to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/BasePage_ja.properties
index 3779b77..3ece231 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/BasePage_ja.properties
@@ -14,12 +14,13 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-username=Username
-securityQuestion=Security Question
-securityAnswer=Security Answer
-reload=Reload
-not.loading=Not loading?
-submit=Submit
-cancel=Cancel
-self.pwd.reset.success=Password successfully reset
-domain=Domain
+home=\u30db\u30fc\u30e0
+version=\u30d0\u30fc\u30b8\u30e7\u30f3
+domain=\u30c9\u30e1\u30a4\u30f3
+
+systemInfo=\u30b7\u30b9\u30c6\u30e0\u60c5\u5831
+hostname=\u30db\u30b9\u30c8\u540d
+processors=\u5229\u7528\u53ef\u80fd\u306a\u30d7\u30ed\u30bb\u30c3\u30b5\u30fc
+os=\u30aa\u30da\u30ec\u30fc\u30c6\u30a3\u30f3\u30b0\u30b7\u30b9\u30c6\u30e0
+jvm=JVM
+lang=ja
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses_ru.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/BasePage_pt_BR.properties
similarity index 81%
copy from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses_ru.properties
copy to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/BasePage_pt_BR.properties
index 7f39171..2bd5964 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses_ru.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/BasePage_pt_BR.properties
@@ -14,5 +14,13 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-#
-auxClasses.palette=\u0412\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043a\u043b\u0430\u0441\u0441\u044b
+home=In\u00edcio
+version=Vers\u00e3o
+domain=Domain
+
+systemInfo=System Information
+hostname=Host Name
+processors=Available Processors
+os=Operating System
+jvm=JVM
+lang=pt
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/BasePage_ru.properties
similarity index 60%
copy from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel.properties
copy to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/BasePage_ru.properties
index 3779b77..93a6ba3 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/BasePage_ru.properties
@@ -14,12 +14,12 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-username=Username
-securityQuestion=Security Question
-securityAnswer=Security Answer
-reload=Reload
-not.loading=Not loading?
-submit=Submit
-cancel=Cancel
-self.pwd.reset.success=Password successfully reset
-domain=Domain
+home=\u0413\u043b\u0430\u0432\u043d\u0430\u044f
+version=\u0412\u0435\u0440\u0441\u0438\u044f
+domain=\u0414\u043e\u043c\u0435\u043d
+systemInfo=\u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u0441\u0438\u0441\u0442\u0435\u043c\u0435
+hostname=\u0418\u043c\u044f \u0445\u043e\u0441\u0442\u0430
+processors=\u041f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u044b
+os=\u041e\u043f\u0435\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u0430\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u0430
+jvm=JVM
+lang=ru
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/DerAttrs.html b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Dashboard.html
similarity index 86%
copy from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/DerAttrs.html
copy to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Dashboard.html
index dfcda58..6f33488 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/DerAttrs.html
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Dashboard.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
@@ -18,9 +19,8 @@
-->
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
<wicket:extend>
- <div wicket:id="derSchemas"/>
- <span wicket:id="membershipsDerSchemas">
- <div wicket:id="membershipDerSchemas"/>
- </span>
+ <section class="content" wicket:id="content">
+ <span wicket:id="userProfileInfo"></span>
+ </section>
</wicket:extend>
-</html>
\ No newline at end of file
+</html>
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Dashboard.properties
similarity index 92%
copy from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties
copy to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Dashboard.properties
index 56c00af..b9100c3 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Dashboard.properties
@@ -14,4 +14,6 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-auxClasses.palette=Auxiliary classes
+overview=Overview
+control=Control
+accessTokens=Access Tokens
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Dashboard_fr_CA.properties
similarity index 90%
copy from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties
copy to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Dashboard_fr_CA.properties
index 56c00af..7cb6b9f 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Dashboard_fr_CA.properties
@@ -14,4 +14,6 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-auxClasses.palette=Auxiliary classes
+overview=R\u00e9sum\u00e9
+control=Contr\u00f4le
+accessTokens=Jetons d'acc\u00e8s
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Dashboard_it.properties
similarity index 91%
copy from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties
copy to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Dashboard_it.properties
index 56c00af..efdaee4 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Dashboard_it.properties
@@ -14,4 +14,6 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-auxClasses.palette=Auxiliary classes
+overview=Sommario
+control=Gestione
+accessTokens=Token di accesso
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Dashboard_ja.properties
similarity index 85%
copy from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties
copy to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Dashboard_ja.properties
index 56c00af..65401fd 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Dashboard_ja.properties
@@ -14,4 +14,6 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-auxClasses.palette=Auxiliary classes
+overview=\u6982\u8981
+control=\u30b3\u30f3\u30c8\u30ed\u30fc\u30eb
+accessTokens=\u30a2\u30af\u30bb\u30b9\u30c8\u30fc\u30af\u30f3
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Dashboard_pt_BR.properties
similarity index 91%
copy from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties
copy to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Dashboard_pt_BR.properties
index 56c00af..5823cf9 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Dashboard_pt_BR.properties
@@ -14,4 +14,6 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-auxClasses.palette=Auxiliary classes
+overview=Resumo
+control=Gest\u00e3o
+accessTokens=Tokens de acesso
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel_pt_BR.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Dashboard_ru.properties
similarity index 69%
copy from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel_pt_BR.properties
copy to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Dashboard_ru.properties
index cf3ca73..23cad85 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel_pt_BR.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Dashboard_ru.properties
@@ -14,12 +14,7 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-username=Nome de usu\u00e1rio\n
-securityQuestion=Pergunta de Seguran\u00e7a
-securityAnswer=Resposta de seguran\u00e7a
-reload=recarregar
-not.loading=N\u00e3o est\u00e1 carregando?
-submit=Enviar
-cancel=Cancelar
-self.pwd.reset.success=Senha redefinida com sucesso
-domain=Domain
+overview=\u041e\u0431\u0437\u043e\u0440
+# control=\u00d0\u00a3\u00d0\u00bf\u00d1\u0080\u00d0\u00b0\u00d0\u00b2\u00d0\u00bb\u00d0\u00b5\u00d0\u00bd\u00d0\u00b8\u00d0\u00b5
+control=\u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435
+accessTokens=\u0442\u043e\u043a\u0435\u043d\u043e\u0432 \u0434\u043e\u0441\u0442\u0443\u043f\u0430
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/PlainAttrs.html b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditChangePassword.html
similarity index 81%
copy from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/PlainAttrs.html
copy to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditChangePassword.html
index 8da9bd9..c0f9fe8 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/PlainAttrs.html
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditChangePassword.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
@@ -18,9 +19,10 @@
-->
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
<wicket:extend>
- <div wicket:id="plainSchemas"/>
- <span wicket:id="membershipsPlainSchemas">
- <div wicket:id="membershipPlainSchemas"/>
- </span>
+ <section class="content" wicket:id="content">
+ <div class="box">
+ <span wicket:id="changePasswordPanel">[CHANGE_PASSWORD_PANEL]</span>
+ </div>
+ </section>
</wicket:extend>
-</html>
\ No newline at end of file
+</html>
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditChangePassword.properties
similarity index 69%
copy from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel.properties
copy to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditChangePassword.properties
index 3779b77..2be6939 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditChangePassword.properties
@@ -14,12 +14,12 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-username=Username
-securityQuestion=Security Question
-securityAnswer=Security Answer
-reload=Reload
-not.loading=Not loading?
-submit=Submit
+password=Password
+submit=Change
cancel=Cancel
-self.pwd.reset.success=Password successfully reset
-domain=Domain
+confirmPassword=Password (confirm)
+passwordNeedsToBeUpdated=Password needs to be updated
+self.pwd.change.success.msg=Password successfully changed
+self.pwd.change.error=Unable to complete the change password
+self.pwd.change.error.msg=Please contact an administrator
+self.pwd.change.success=Successfully changed
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditChangePassword_fr_CA.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditChangePassword_fr_CA.properties
new file mode 100644
index 0000000..eb20e46
--- /dev/null
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditChangePassword_fr_CA.properties
@@ -0,0 +1,24 @@
+#
+# Copyright (C) 2020 Tirasa (info@tirasa.net)
+#
+# Licensed 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.
+#
+password=Mot de passe
+submit=Modifier
+cancel=Annuler
+confirmPassword=Confirmer le mot de passe
+passwordNeedsToBeUpdated=Le mot de passe doit \u00eatre mis \u00e0 jour
+self.pwd.change.success.msg=Mot de passe chang\u00e9 avec succ\u00e8s
+self.pwd.change.error=Impossible de terminer le changement de mot de passe
+self.pwd.change.error.msg=Veuillez contacter un administrateur
+self.pwd.change.success=Modifi\u00e9 avec succ\u00e8s
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel_it.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditChangePassword_it.properties
similarity index 69%
copy from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel_it.properties
copy to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditChangePassword_it.properties
index 5519bc4..0044ab1 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel_it.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditChangePassword_it.properties
@@ -14,12 +14,12 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-username=Username
-securityQuestion=Domanda di sicurezza
-securityAnswer=Risposta di sicurezza
-reload=Ricarica
-not.loading=Non carica?
-submit=Salva
+password=Password
+submit=Cambia
cancel=Annulla
-self.pwd.reset.success=La password \u00e8 stata resettata con successo
-domain=Dominio
+confirmPassword=Password (conferma)
+passwordNeedsToBeUpdated=La password deve essere aggiornata
+self.pwd.change.success.msg=Password aggiornata con successo
+self.pwd.change.error=Errore durante il cambio password
+self.pwd.change.error.msg=Si prega di contattare
+self.pwd.change.success=Aggiornamento avvenuto con successo
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditChangePassword_ja.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditChangePassword_ja.properties
new file mode 100644
index 0000000..9361a16
--- /dev/null
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditChangePassword_ja.properties
@@ -0,0 +1,25 @@
+# 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.
+password=\u30d1\u30b9\u30ef\u30fc\u30c9
+submit=\u5909\u66f4
+cancel=\u30ad\u30e3\u30f3\u30bb\u30eb
+confirmPassword=\u30d1\u30b9\u30ef\u30fc\u30c9 (\u78ba\u8a8d)
+passwordNeedsToBeUpdated=\u30d1\u30b9\u30ef\u30fc\u30c9\u3092\u66f4\u65b0\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059
+self.pwd.change.success.msg=\u30d1\u30b9\u30ef\u30fc\u30c9\u304c\u6b63\u5e38\u306b\u5909\u66f4\u3055\u308c\u307e\u3057\u305f
+self.pwd.change.error=\u30d1\u30b9\u30ef\u30fc\u30c9\u306e\u5909\u66f4\u3092\u5b8c\u4e86\u3067\u304d\u307e\u305b\u3093
+self.pwd.change.error.msg=\u30d1\u30b9\u30ef\u30fc\u30c9\u30ea\u30bb\u30c3\u30c8\u306e\u78ba\u8a8d\u3092\u5b8c\u4e86\u3067\u304d\u307e\u305b\u3093
+self.pwd.change.success=\u6b63\u5e38\u306b\u5909\u66f4\u3055\u308c\u307e\u3057\u305f
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel_pt_BR.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditChangePassword_pt_BR.properties
similarity index 69%
copy from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel_pt_BR.properties
copy to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditChangePassword_pt_BR.properties
index cf3ca73..a54d215 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel_pt_BR.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditChangePassword_pt_BR.properties
@@ -14,12 +14,13 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-username=Nome de usu\u00e1rio\n
-securityQuestion=Pergunta de Seguran\u00e7a
-securityAnswer=Resposta de seguran\u00e7a
-reload=recarregar
-not.loading=N\u00e3o est\u00e1 carregando?
-submit=Enviar
+password=Senha
+submit=Alterar
+confirmPassword=Senha (confirmar)
+passwordNeedsToBeUpdated=Senha precisa ser atualizado
+self.pwd.change.success.msg=Senha mudada com sucesso
+
+self.pwd.change.error=Incapaz de completar a mudan\u00e7a de senha
+self.pwd.change.error.msg=Incapaz de completar a mudan\u00e7a de senha
+self.pwd.change.success=Alterado com sucesso
cancel=Cancelar
-self.pwd.reset.success=Senha redefinida com sucesso
-domain=Domain
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditChangePassword_ru.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditChangePassword_ru.properties
new file mode 100644
index 0000000..dc396f8
--- /dev/null
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditChangePassword_ru.properties
@@ -0,0 +1,28 @@
+# 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.
+password=\u041f\u0430\u0440\u043e\u043b\u044c
+# submit=\u00d0\u0098\u00d0\u00b7\u00d0\u00bc\u00d0\u00b5\u00d0\u00bd\u00d0\u00b8\u00d1\u0082\u00d1\u008c
+submit=\u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c
+cancel=\u043e\u0442\u043c\u0435\u043d\u0438\u0442\u044c
+#confirmPassword=\u00d0\u009f\u00d0\u00b0\u00d1\u0080\u00d0\u00be\u00d0\u00bb\u00d1\u008c (\u00d0\u00bf\u00d0\u00be\u00d0\u00b4\u00d1\u0082\u00d0\u00b2\u00d0\u00b5\u00d1\u0080\u00d0\u00b6\u00d0\u00b4\u00d0\u00b5\u00d0\u00bd\u00d0\u00b8\u00d0\u00b5)
+confirmPassword=\u041f\u0430\u0440\u043e\u043b\u044c (\u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435)
+# passwordNeedsToBeUpdated=\u00d0\u009f\u00d0\u00b0\u00d1\u0080\u00d0\u00be\u00d0\u00bb\u00d1\u008c \u00d0\u00b4\u00d0\u00be\u00d0\u00bb\u00d0\u00b6\u00d0\u00b5\u00d0\u00bd \u00d0\u00b1\u00d1\u008b\u00d1\u0082\u00d1\u008c \u00d0\u00b8\u00d0\u00b7\u00d0\u00bc\u00d0\u00b5\u00d0\u00bd\u00d1\u0091\u00d0\u00bd
+passwordNeedsToBeUpdated=\u041f\u0430\u0440\u043e\u043b\u044c \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0451\u043d
+self.pwd.change.success.msg=\u041f\u0430\u0440\u043e\u043b\u044c \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0438\u0437\u043c\u0435\u043d\u0435\u043d
+self.pwd.change.error=\u041d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044c \u0441\u043c\u0435\u043d\u0443 \u043f\u0430\u0440\u043e\u043b\u044f
+self.pwd.change.error.msg=\u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0441\u0432\u044f\u0436\u0438\u0442\u0435\u0441\u044c \u0441 \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u043e\u043c
+self.pwd.change.success=\u0423\u0441\u043f\u0435\u0448\u043d\u043e \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u043e
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditSecurityQuestion.html b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditSecurityQuestion.html
new file mode 100644
index 0000000..d4c0a0b
--- /dev/null
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditSecurityQuestion.html
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<!--
+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.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
+ <wicket:extend>
+ <section class="content" wicket:id="content">
+ <div class="box">
+ <div class="row clearfix">
+ <div class="col-md-12">
+ <div class="col-md-6 mx-auto">
+ <!-- form start -->
+ <form wicket:id="securityQuestionForm" class="form-horizontal">
+ <div class="box-body">
+ <div class="box-header formcard">
+ <header class="card-container bg-danger">
+ <label class="card-header-style">Security Question</label>
+ </header>
+ <div class="card-container-body">
+ <div>
+ <div class="col-xs-12">
+ <div class="form-group">
+ <span wicket:id="securityQuestion">[SECURITY QUESTION]</span>
+ </div>
+ <div class="form-group">
+ <span wicket:id="securityAnswer">[SECURITY ANSWER]</span>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <span wicket:id="captchaPanelCard"/>
+ </div>
+ <div class="box-footer">
+ <input id="submit_button" wicket:id="submit" type="submit" wicket:message="value:submit"
+ class="btn btn-success float-right"/>
+ <input id="cancel_button" wicket:id="cancel" type="submit" wicket:message="value:cancel"
+ class="btn btn-default float-left"/>
+ </div>
+ </form>
+ <!-- /.box-body -->
+ </div>
+ </div>
+ </div>
+ </div>
+ </section>
+ </wicket:extend>
+</html>
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditSecurityQuestion.properties
similarity index 71%
copy from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel.properties
copy to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditSecurityQuestion.properties
index 3779b77..2a001b7 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditSecurityQuestion.properties
@@ -14,12 +14,10 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-username=Username
-securityQuestion=Security Question
-securityAnswer=Security Answer
-reload=Reload
-not.loading=Not loading?
-submit=Submit
+password=Password
+submit=Change
cancel=Cancel
-self.pwd.reset.success=Password successfully reset
-domain=Domain
+self.securityquestion.change.success=Successfully changed
+self.securityquestion.change.error=Unable to change the security question
+self.securityquestion.change.error.msg=Please contact an administrator
+self.securityquestion.change.success.msg=Security question changed successfully
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel_it.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditSecurityQuestion_it.properties
similarity index 68%
copy from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel_it.properties
copy to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditSecurityQuestion_it.properties
index 5519bc4..deec620 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel_it.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditSecurityQuestion_it.properties
@@ -14,12 +14,10 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-username=Username
-securityQuestion=Domanda di sicurezza
-securityAnswer=Risposta di sicurezza
-reload=Ricarica
-not.loading=Non carica?
-submit=Salva
+password=Password
+submit=Cambia
cancel=Annulla
-self.pwd.reset.success=La password \u00e8 stata resettata con successo
-domain=Dominio
+self.securityquestion.change.success=Aggiornamento avvenuto con successo
+self.securityquestion.change.error=Errore durante il cambio della domanda di sicurezza
+self.securityquestion.change.error.msg=Si prega di contattare
+self.securityquestion.change.success.msg=Aggiornamento della domanda di sicurezza avvenuto con successo
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditSecurityQuestion_ja.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditSecurityQuestion_ja.properties
new file mode 100644
index 0000000..a5a6bcb
--- /dev/null
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditSecurityQuestion_ja.properties
@@ -0,0 +1,23 @@
+# 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.
+password=\u30d1\u30b9\u30ef\u30fc\u30c9
+submit=\u5909\u66f4
+cancel=\u30ad\u30e3\u30f3\u30bb\u30eb
+self.securityquestion.change.success=\u6b63\u5e38\u306b\u5909\u66f4\u3055\u308c\u307e\u3057\u305f
+self.securityquestion.change.error=\u30d1\u30b9\u30ef\u30fc\u30c9\u306e\u5909\u66f4\u3092\u5b8c\u4e86\u3067\u304d\u307e\u305b\u3093
+self.securityquestion.change.error.msg=\u30d1\u30b9\u30ef\u30fc\u30c9\u30ea\u30bb\u30c3\u30c8\u306e\u78ba\u8a8d\u3092\u5b8c\u4e86\u3067\u304d\u307e\u305b\u3093
+self.securityquestion.change.success.msg=\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3\u306e\u8cea\u554f\u304c\u6b63\u5e38\u306b\u5909\u66f4\u3055\u308c\u307e\u3057\u305f
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel_pt_BR.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditSecurityQuestion_pt_BR.properties
similarity index 69%
copy from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel_pt_BR.properties
copy to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditSecurityQuestion_pt_BR.properties
index cf3ca73..7ded2eb 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel_pt_BR.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditSecurityQuestion_pt_BR.properties
@@ -14,12 +14,10 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-username=Nome de usu\u00e1rio\n
-securityQuestion=Pergunta de Seguran\u00e7a
-securityAnswer=Resposta de seguran\u00e7a
-reload=recarregar
-not.loading=N\u00e3o est\u00e1 carregando?
-submit=Enviar
-cancel=Cancelar
-self.pwd.reset.success=Senha redefinida com sucesso
-domain=Domain
+password=Senha
+submit=Alterar
+self.securityquestion.change.success=Alterado com sucesso
+
+self.securityquestion.change.error=Incapaz de completar a mudan\u00e7a de senha
+self.securityquestion.change.error.msg=Incapaz de completar a mudan\u00e7a de senha
+self.securityquestion.change.success.msg=Pergunta de seguran\u00e7a alterada com sucesso
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditSecurityQuestion_ru.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditSecurityQuestion_ru.properties
new file mode 100644
index 0000000..616ccfa
--- /dev/null
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditSecurityQuestion_ru.properties
@@ -0,0 +1,24 @@
+# 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.
+password=\u041f\u0430\u0440\u043e\u043b\u044c
+# submit=\u00d0\u0098\u00d0\u00b7\u00d0\u00bc\u00d0\u00b5\u00d0\u00bd\u00d0\u00b8\u00d1\u0082\u00d1\u008c
+submit=\u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c
+cancel=\u043e\u0442\u043c\u0435\u043d\u0438\u0442\u044c
+self.securityquestion.change.success=\u0423\u0441\u043f\u0435\u0448\u043d\u043e \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u043e
+self.securityquestion.change.error=\u041d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044c \u0441\u043c\u0435\u043d\u0443 \u043f\u0430\u0440\u043e\u043b\u044f
+self.securityquestion.change.error.msg=\u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0441\u0432\u044f\u0436\u0438\u0442\u0435\u0441\u044c \u0441 \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u043e\u043c
+self.securityquestion.change.success.msg=\u041a\u043e\u043d\u0442\u0440\u043e\u043b\u044c\u043d\u044b\u0439 \u0432\u043e\u043f\u0440\u043e\u0441 \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0438\u0437\u043c\u0435\u043d\u0435\u043d
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/PlainAttrs.html b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditUser.html
similarity index 72%
copy from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/PlainAttrs.html
copy to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditUser.html
index 8da9bd9..1a47856 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/PlainAttrs.html
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditUser.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
@@ -18,9 +19,15 @@
-->
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
<wicket:extend>
- <div wicket:id="plainSchemas"/>
- <span wicket:id="membershipsPlainSchemas">
- <div wicket:id="membershipPlainSchemas"/>
- </span>
+ <section class="content" wicket:id="content">
+ <div class="row clearfix">
+ <!-- left column -->
+ <div class="col-md-12">
+ <div class="col-md-12 column box">
+ <span wicket:id="editUserPanel"></span>
+ </div>
+ </div>
+ </div><!-- </div> -->
+ </section>
</wicket:extend>
-</html>
\ No newline at end of file
+</html>
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditUser.properties
similarity index 84%
copy from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties
copy to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditUser.properties
index 56c00af..633e2c5 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditUser.properties
@@ -14,4 +14,10 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-auxClasses.palette=Auxiliary classes
+overview=Overview
+control=Control
+accessTokens=Access Tokens
+palette.available=Available
+palette.selected=Selected
+submit=Change
+cancel=Cancel
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditUser_fr_CA.properties
similarity index 91%
copy from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties
copy to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditUser_fr_CA.properties
index 56c00af..233a893 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditUser_fr_CA.properties
@@ -14,4 +14,6 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-auxClasses.palette=Auxiliary classes
+overview=R�sum�
+control=Contr�le
+accessTokens=Jetons d'acc�s
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditUser_it.properties
similarity index 91%
copy from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties
copy to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditUser_it.properties
index 56c00af..efdaee4 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditUser_it.properties
@@ -14,4 +14,6 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-auxClasses.palette=Auxiliary classes
+overview=Sommario
+control=Gestione
+accessTokens=Token di accesso
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditUser_ja.properties
similarity index 85%
copy from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties
copy to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditUser_ja.properties
index 56c00af..65401fd 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditUser_ja.properties
@@ -14,4 +14,6 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-auxClasses.palette=Auxiliary classes
+overview=\u6982\u8981
+control=\u30b3\u30f3\u30c8\u30ed\u30fc\u30eb
+accessTokens=\u30a2\u30af\u30bb\u30b9\u30c8\u30fc\u30af\u30f3
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditUser_pt_BR.properties
similarity index 91%
copy from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties
copy to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditUser_pt_BR.properties
index 56c00af..5823cf9 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditUser_pt_BR.properties
@@ -14,4 +14,6 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-auxClasses.palette=Auxiliary classes
+overview=Resumo
+control=Gest\u00e3o
+accessTokens=Tokens de acesso
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel_pt_BR.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditUser_ru.properties
similarity index 69%
copy from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel_pt_BR.properties
copy to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditUser_ru.properties
index cf3ca73..23cad85 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel_pt_BR.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/EditUser_ru.properties
@@ -14,12 +14,7 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-username=Nome de usu\u00e1rio\n
-securityQuestion=Pergunta de Seguran\u00e7a
-securityAnswer=Resposta de seguran\u00e7a
-reload=recarregar
-not.loading=N\u00e3o est\u00e1 carregando?
-submit=Enviar
-cancel=Cancelar
-self.pwd.reset.success=Senha redefinida com sucesso
-domain=Domain
+overview=\u041e\u0431\u0437\u043e\u0440
+# control=\u00d0\u00a3\u00d0\u00bf\u00d1\u0080\u00d0\u00b0\u00d0\u00b2\u00d0\u00bb\u00d0\u00b5\u00d0\u00bd\u00d0\u00b8\u00d0\u00b5
+control=\u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435
+accessTokens=\u0442\u043e\u043a\u0435\u043d\u043e\u0432 \u0434\u043e\u0441\u0442\u0443\u043f\u0430
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Login.html b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Login.html
index abafe9e..55c8ab6 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Login.html
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Login.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
@@ -32,13 +33,14 @@
<link href="ui-commons/css/login.css" rel="stylesheet" type="text/css" />
<link href="ui-commons/css/syncopeUI.css" rel="stylesheet" type="text/css"/>
+ <link href="css/syncopeEnduser.css" rel="stylesheet" type="text/css"/>
<!-- accessibility -->
<link href="ui-commons/css/accessibility.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="ui-commons/js/accessibility.js"></script>
</head>
- <body class="login-body login_enduser">
+ <body class="login-body">
<div id="accessibility">
<div id="change_contrast" class="btn-accessibility">
<i aria-label="Toggle high contrast colors mode" tabindex="0" accesskey="H"
@@ -51,13 +53,12 @@
</i>
</div>
</div>
-
<div class="container">
<div class="login-card card card-container">
<img class="login-logo" src="ui-commons/img/logo-green.png" />
<span wicket:id="feedback" role="alert"/>
- <div class="box alert-danger" style="padding: 5px;text-align: center;" wicket:id="exceptionMessage"/>
+ <div class="alert-danger" style="padding: 5px;text-align: center;" wicket:id="exceptionMessage"/>
<form class="form-signin" wicket:id="login">
<fieldset class="form-group">
@@ -75,7 +76,7 @@
<select class="form-control select2bs4 select2-hidden-accessible" wicket:id="domain"/>
</div>
- <button wicket:id="submit" type="submit" class="btn btn-lg btn-primary btn-block btn-signin"></button>
+ <button wicket:id="submit" type="submit" class="btn btn-lg btn-primary btn-block btn-signin bg-danger"></button>
</fieldset>
<div wicket:id="ssoLogins">
@@ -84,11 +85,9 @@
</form>
<div class="text-center login_link">
+ <a wicket:id="self-pwd-reset"><wicket:message key="self-pwd-reset">[SELFPWDRESET]</wicket:message></a><br/>
<a wicket:id="self-registration"><wicket:message key="self-registration">[SELFREGISTRATION]</wicket:message></a>
</div>
- <div class="text-center login_link">
- <a wicket:id="self-pwd-reset"><wicket:message key="self-pwd-reset">[SELFPWDRESET]</wicket:message></a>
- </div>
</div>
</div>
</body>
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Login_ru.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Login_ru.properties
index 46f2f2f..151e3f1 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Login_ru.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Login_ru.properties
@@ -14,7 +14,6 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-# username=\u00d0\u0098\u00d0\u00bc\u00d1\u008f \u00d0\u00bf\u00d0\u00be\u00d0\u00bb\u00d1\u008c\u00d0\u00b7\u00d0\u00be\u00d0\u00b2\u00d0\u00b0\u00d1\u0082\u00d0\u00b5\u00d0\u00bb\u00d1\u008f
username=\u0418\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f
# password=\u00d0\u009f\u00d0\u00b0\u00d1\u0080\u00d0\u00be\u00d0\u00bb\u00d1\u008c
password=\u041f\u0430\u0440\u043e\u043b\u044c
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/MustChangePassword.html b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/MustChangePassword.html
index 7f68e1a..905836c 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/MustChangePassword.html
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/MustChangePassword.html
@@ -17,87 +17,18 @@
specific language governing permissions and limitations
under the License.
-->
-<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org" class="max_height">
- <head>
- <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
- <meta charset="UTF-8"/>
- <meta content='width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no' name='viewport'/>
-
- <title>Apache Syncope - Change password</title>
-
- <link rel="shortcut icon" href="ui-commons/img/favicon.png" type="image/png"/>
-
- <link href="webjars/font-awesome/${font-awesome.version}/css/all.min.css" rel="stylesheet" type="text/css" />
- <link href="webjars/ionicons/${ionicons.version}/css/ionicons.min.css" rel="stylesheet" type="text/css" />
- <link href="ui-commons/css/fonts.css" rel="stylesheet" type="text/css"/>
-
- <link href="ui-commons/css/syncopeUI.css" rel="stylesheet" type="text/css"/>
-
- <!-- accessibility -->
- <link href="ui-commons/css/accessibility.css" rel="stylesheet" type="text/css" />
- <script type="text/javascript" src="ui-commons/js/accessibility.js"></script>
- </head>
-
- <body class="max_height">
- <div id="accessibility">
- <div id="change_contrast" class="btn-accessibility">
- <i aria-label="Toggle high contrast colors mode" tabindex="0" accesskey="H"
- class="fa fa-adjust">
- </i>
- </div>
- <div id="change_fontSize" class="btn-accessibility">
- <i aria-label="Toggle font size increment" tabindex="1" accesskey="F"
- class="fa fa-font">
- </i>
- </div>
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
+ <wicket:extend>
+ <div class="brand-link bg-red brand-custom">
+ <span class="logo-mini">
+ <img aria-label="Apache Syncope Enduser" alt="Apache Syncope Enduser" src="ui-commons/img/logo-mini.png"/>
+ </span>
+ <span class="brand-text font-weight-light">Apache Syncope</span>
</div>
-
- <div id="mcp_wrapper" class="wrapper">
- <div class="content-wrapper">
- <div class="card card-container vertical_align">
-
- <div class="custom_content_wrapper">
- <div class="col-xs-12">
- <img id="mcp_logo" class="login-logo" src="ui-commons/img/logo-green.png" />
-
- <span wicket:id="feedback"></span>
-
- <div class="alert alert-success"><wicket:message key="passwordNeedsToBeUpdated"/></div>
- </div>
-
- <div class="col-xs-12">
-
- <div id="mcp_form" class="container-fluid password_reset_wrapper">
- <div class="row">
- <div class="col-md-6 col-md-offset-3">
- <form wicket:id="changePassword" class="form-horizontal">
- <fieldset class="enduser_fieldset">
- <div class="form-group input-md">
- <input type="text" wicket:id="username" id="username" class="form-control"
- wicket:message="placeholder:username" required="required" autofocus="autofocus" />
- </div>
- <span id="password" wicket:id="password" class="form-group input-md"/>
- <span id="confirmPassword" wicket:id="confirmPassword" class="form-group input-md"/>
-
- <div class="password_reset_buttons form-group">
- <div class="col-md-6">
- <input id="cancel_button" wicket:id="cancel" type="submit" wicket:message="value:cancel"
- class="btn btn-default float-left"/>
- </div>
- <div class="col-md-6">
- <input id="submit_button" wicket:id="submit" type="submit" wicket:message="value:submit"
- class="btn btn-primary float-right"/>
- </div>
- </div>
- </fieldset>
- </form>
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
+ <section class="content" wicket:id="content">
+ <div class="box">
+ <span wicket:id="changePasswordPanel">[CHANGE_PASSWORD_PANEL]</span>
</div>
- </div>
- </body>
+ </section>
+ </wicket:extend>
</html>
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/MustChangePassword.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/MustChangePassword.properties
index f69fef9..899a97c 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/MustChangePassword.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/MustChangePassword.properties
@@ -21,3 +21,6 @@
confirmPassword=Password (confirm)
passwordNeedsToBeUpdated=Password needs to be updated
self.pwd.change.success=Password successfully changed
+Cancel=Cancel
+self.pwd.change.error=Unable to complete the change password
+self.pwd.change.error.msg=Please contact an administrator
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/MustChangePassword_it.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/MustChangePassword_it.properties
index 0d65dc4..caa926b 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/MustChangePassword_it.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/MustChangePassword_it.properties
@@ -22,3 +22,6 @@
passwordNeedsToBeUpdated=La password deve essere aggiornata
self.pwd.change.success=Password aggiornata con successo
+Cancel=Annulla
+self.pwd.change.error=Errore durante il cambio password
+self.pwd.change.error.msg=Si prega di contattare
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/MustChangePassword_ja.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/MustChangePassword_ja.properties
index 34bb07c..ea0d5bf 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/MustChangePassword_ja.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/MustChangePassword_ja.properties
@@ -22,3 +22,6 @@
passwordNeedsToBeUpdated=\u30d1\u30b9\u30ef\u30fc\u30c9\u3092\u66f4\u65b0\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059
self.pwd.change.success=\u30d1\u30b9\u30ef\u30fc\u30c9\u304c\u6b63\u5e38\u306b\u5909\u66f4\u3055\u308c\u307e\u3057\u305f
+Cancel=\u30ad\u30e3\u30f3\u30bb\u30eb
+self.pwd.change.error=\u30d1\u30b9\u30ef\u30fc\u30c9\u306e\u5909\u66f4\u3092\u5b8c\u4e86\u3067\u304d\u307e\u305b\u3093
+self.pwd.change.error.msg=\u30d1\u30b9\u30ef\u30fc\u30c9\u30ea\u30bb\u30c3\u30c8\u306e\u78ba\u8a8d\u3092\u5b8c\u4e86\u3067\u304d\u307e\u305b\u3093
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/MustChangePassword_pt_BR.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/MustChangePassword_pt_BR.properties
index 3390349..f5e4aba 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/MustChangePassword_pt_BR.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/MustChangePassword_pt_BR.properties
@@ -22,3 +22,5 @@
passwordNeedsToBeUpdated=Senha precisa ser atualizado
self.pwd.change.success=Senha mudada com sucesso
+self.pwd.change.error=Incapaz de completar a mudan\u00e7a de senha
+self.pwd.change.error.msg=Incapaz de completar a mudan\u00e7a de senha
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/MustChangePassword_ru.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/MustChangePassword_ru.properties
index e2c504c..1d7af16 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/MustChangePassword_ru.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/MustChangePassword_ru.properties
@@ -14,8 +14,6 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-#
-# username=\u00d0\u0098\u00d0\u00bc\u00d1\u008f \u00d0\u00bf\u00d0\u00be\u00d0\u00bb\u00d1\u008c\u00d0\u00b7\u00d0\u00be\u00d0\u00b2\u00d0\u00b0\u00d1\u0082\u00d0\u00b5\u00d0\u00bb\u00d1\u008f
username=\u0418\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f
# password=\u00d0\u009f\u00d0\u00b0\u00d1\u0080\u00d0\u00be\u00d0\u00bb\u00d1\u008c
password=\u041f\u0430\u0440\u043e\u043b\u044c
@@ -28,3 +26,6 @@
passwordNeedsToBeUpdated=\u041f\u0430\u0440\u043e\u043b\u044c \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0451\u043d
self.pwd.change.success=\u041f\u0430\u0440\u043e\u043b\u044c \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0438\u0437\u043c\u0435\u043d\u0435\u043d
+Cancel=\u041e\u0442\u043c\u0435\u043d\u0430
+self.pwd.change.error=\u041d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044c \u0441\u043c\u0435\u043d\u0443 \u043f\u0430\u0440\u043e\u043b\u044f
+self.pwd.change.error.msg=\u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0441\u0432\u044f\u0436\u0438\u0442\u0435\u0441\u044c \u0441 \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u043e\u043c
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Self.html b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Self.html
index 6124f0c..c16e43f 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Self.html
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Self.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfConfirmPasswordReset.html b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfConfirmPasswordReset.html
index 1a6f8a8..9ec6f04 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfConfirmPasswordReset.html
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfConfirmPasswordReset.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
@@ -18,43 +19,38 @@
-->
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
<wicket:extend>
-
+ <div class="brand-link bg-red brand-custom">
+ <span class="logo-mini">
+ <img aria-label="Apache Syncope Enduser" alt="Apache Syncope Enduser" src="ui-commons/img/logo-mini.png"/>
+ </span>
+ <span class="brand-text font-weight-light">Apache Syncope</span>
+ </div>
<section class="content" wicket:id="content">
- <div id="confirm_password_reset" class="container-fluid password_reset_wrapper">
+ <div class="box">
+ <div id="confirm_password_reset" class="container-fluid password_reset_wrapper">
- <div class="row">
- <div class="col-md-6 col-md-offset-3">
-
+ <div class="col-md-6 mx-auto">
<div class="page-header">
<h1>
<wicket:message key="confirm-reset">[CONFIRM_PASSWORD_RESET]</wicket:message>
</h1>
</div>
- <form wicket:id="selfConfirmPwdResetForm" class="form-horizontal">
- <fieldset class="enduser_fieldset">
- <select wicket:id="domain" class="form-group input-md"/>
- <span id="password" wicket:id="password" class="form-group input-md"/>
- <span id="confirmPassword" wicket:id="confirmPassword" class="form-group input-md"/>
+ <form wicket:id="selfConfirmPwdResetForm">
+ <div class="box-body">
+ <span wicket:id="selfConfirmPasswordResetPanelCard">[CONFIRM_PASSWORD_RESET]</span>
+ </div>
- <div class="password_reset_buttons form-group">
- <div class="col-md-6">
- <input id="cancel_button" wicket:id="cancel" type="submit" wicket:message="value:cancel"
- class="btn btn-default float-left"/>
- </div>
- <div class="col-md-6">
- <input id="submit_button" wicket:id="submit" type="submit" wicket:message="value:submit"
- class="btn btn-primary float-right"/>
- </div>
- </div>
- </fieldset>
+ <div class="box-footer">
+ <input id="cancel_button" wicket:id="cancel" type="submit" wicket:message="value:cancel"
+ class="btn btn-default float-left"/>
+ <input id="submit_button" wicket:id="submit" type="submit" wicket:message="value:submit"
+ class="btn btn-primary float-right"/>
+ </div>
</form>
-
</div> <!-- col -->
- </div> <!-- row -->
-
+ </div>
</div>
</section>
-
</wicket:extend>
</html>
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfConfirmPasswordReset.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfConfirmPasswordReset.properties
index 8d7d59c..05f050b 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfConfirmPasswordReset.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfConfirmPasswordReset.properties
@@ -20,5 +20,9 @@
password-strength=Password strength:
cancel=Cancel
submit=Submit
-self.confirm.pwd.reset.success=Password successfully reset
+self.confirm.pwd.reset.success=Password Changed!
+self.confirm.pwd.reset.success.msg=Password successfully changed
self.confirm.pwd.reset.error.empty=No token was specified in the url, cannot access to the requested page
+
+self.confirm.pwd.reset.error=Unable to complete the Password Reset
+self.confirm.pwd.reset.error.msg=Please contact an administrator
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfConfirmPasswordReset_it.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfConfirmPasswordReset_it.properties
index e5fffa1..c924560 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfConfirmPasswordReset_it.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfConfirmPasswordReset_it.properties
@@ -20,5 +20,9 @@
password-strength=Sicurezza della password:
cancel=Annulla
submit=Invia
-self.confirm.pwd.reset.success=Password resettata con successo
+self.confirm.pwd.reset.success=Password \u00e8 stata modificata
+self.confirm.pwd.reset.success.msg=Cambio password eseguito con successo
self.confirm.pwd.reset.error.empty=Nessun token \u00e8 specifico nell'url, non \u00e8 possibile accedere alla pagina richiesta
+
+self.confirm.pwd.reset.error=Errore durante il processo di reset password
+self.confirm.pwd.reset.error.msg=Si prega di contattare
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfConfirmPasswordReset_ja.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfConfirmPasswordReset_ja.properties
index 4a2e3a3..7703a33 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfConfirmPasswordReset_ja.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfConfirmPasswordReset_ja.properties
@@ -22,3 +22,6 @@
submit=\u63d0\u51fa\u3059\u308b
self.confirm.pwd.reset.success=\u30d1\u30b9\u30ef\u30fc\u30c9\u3092\u30ea\u30bb\u30c3\u30c8\u3057\u307e\u3057\u305f
self.confirm.pwd.reset.error.empty=URL\u306b\u30c8\u30fc\u30af\u30f3\u304c\u6307\u5b9a\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002\u8981\u6c42\u3055\u308c\u305f\u30da\u30fc\u30b8\u306b\u30a2\u30af\u30bb\u30b9\u3067\u304d\u307e\u305b\u3093
+self.confirm.pwd.reset.success.msg=Password Changed!
+self.confirm.pwd.reset.error=\u30d1\u30b9\u30ef\u30fc\u30c9\u30ea\u30bb\u30c3\u30c8\u306e\u78ba\u8a8d\u3092\u5b8c\u4e86\u3067\u304d\u307e\u305b\u3093
+self.confirm.pwd.reset.error.msg=\u7ba1\u7406\u8005\u306b\u9023\u7d61\u3057\u3066\u304f\u3060\u3055\u3044
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfConfirmPasswordReset_pt_BR.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfConfirmPasswordReset_pt_BR.properties
index da4c530..88202f9 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfConfirmPasswordReset_pt_BR.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfConfirmPasswordReset_pt_BR.properties
@@ -21,4 +21,7 @@
cancel=Cancelar
submit=Enviar
self.confirm.pwd.reset.success=Senha redefinida com sucesso
+self.confirm.pwd.reset.success.msg=Senha redefinida com sucesso
self.confirm.pwd.reset.error.empty=Nenhum token foi especificado na URL, n\u00e3o pode acessar a p\u00e1gina solicitada
+self.confirm.pwd.reset.error=Incapaz de completar a redefini\u00e7\u00e3o de senha
+self.confirm.pwd.reset.error.msg=Incapaz de completar a mudan\u00e7a de senha
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfConfirmPasswordReset_ru.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfConfirmPasswordReset_ru.properties
index 03d5fc4..a1445b8 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfConfirmPasswordReset_ru.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfConfirmPasswordReset_ru.properties
@@ -20,5 +20,9 @@
password-strength=\u041d\u0430\u0434\u0435\u0436\u043d\u043e\u0441\u0442\u044c \u041f\u0430\u0440\u043e\u043b\u044f:
cancel=\u043e\u0442\u043c\u0435\u043d\u0438\u0442\u044c
submit=\u041e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c
-self.confirm.pwd.reset.success==\u041f\u0430\u0440\u043e\u043b\u044c \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0441\u0431\u0440\u043e\u0448\u0435\u043d
+self.confirm.pwd.reset.success=\u041f\u0430\u0440\u043e\u043b\u044c \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0441\u0431\u0440\u043e\u0448\u0435\u043d
+self.confirm.pwd.reset.success.msg=\u041f\u0430\u0440\u043e\u043b\u044c \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0441\u0431\u0440\u043e\u0448\u0435\u043d
self.confirm.pwd.reset.error.empty=\u0412 URL \u043d\u0435 \u0443\u043a\u0430\u0437\u0430\u043d \u0442\u043e\u043a\u0435\u043d, \u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u043c\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435
+
+self.confirm.pwd.reset.error=\u041d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044c \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u0441\u0431\u0440\u043e\u0441\u0430 \u043f\u0430\u0440\u043e\u043b\u044f
+self.confirm.pwd.reset.error.msg=\u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0441\u0432\u044f\u0436\u0438\u0442\u0435\u0441\u044c \u0441 \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u043e\u043c
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel.html b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfPasswordReset$SelfPwdResetPanel.html
similarity index 66%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel.html
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfPasswordReset$SelfPwdResetPanel.html
index 04d76a6..4b11cb8 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel.html
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfPasswordReset$SelfPwdResetPanel.html
@@ -21,10 +21,6 @@
<wicket:panel>
<fieldset class="enduser_fieldset">
- <div class="form-group input-md">
- <label for="domain"><wicket:message key="domain"/></label>
- <select wicket:id="domain" class="form-control"/>
- </div>
<div class="form-group input-md">
<label for="username"><wicket:message key="username"/></label>
@@ -33,15 +29,16 @@
autofocus="autofocus" />
</div>
<div class="form-group input-md">
- <label for="securityQuestion"><wicket:message key="securityQuestion"/></label>
+ <label for="securityQuestion" wicket:id="securityQuestionLabel">[LABEL]</label>
<input id="securityQuestion" type="text" wicket:id="securityQuestion" class="form-control"
wicket:message="placeholder:securityQuestion"
autofocus="autofocus" />
- <div class="suggestions">(<wicket:message key="not.loading">
- </wicket:message><a wicket:id="reloadLink"> <wicket:message key="reload"></wicket:message></a>)</div>
+ <div class="suggestions"><label wicket:id="not.loading">([LABEL])</label>
+ <a wicket:id="reloadLink"> <wicket:message key="reload"></wicket:message></a>
+ </div>
</div>
<div class="form-group input-md">
- <label for="securityAnswer"><wicket:message key="securityAnswer"/></label>
+ <label for="securityAnswer" wicket:id="securityAnswerLabel">[LABEL]</label>
<input id="securityAnswer" type="text" wicket:id="securityAnswer" class="form-control"
wicket:message="placeholder:securityAnswer"
autofocus="autofocus" />
@@ -50,16 +47,6 @@
<span wicket:id="captchaPanel">[CAPTCHA]</span>
</div>
- <div class="password_reset_buttons form-group">
- <div class="col-md-6">
- <input wicket:id="cancel" type="submit" wicket:message="value:cancel"
- class="btn btn-default float-left"/>
- </div>
- <div class="col-md-6">
- <input wicket:id="submit" type="submit" wicket:message="value:submit"
- class="btn btn-success float-right"/>
- </div>
- </div>
</fieldset>
</wicket:panel>
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfPasswordReset$SelfPwdResetPanel.properties
similarity index 93%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel.properties
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfPasswordReset$SelfPwdResetPanel.properties
index 3779b77..73ca456 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfPasswordReset$SelfPwdResetPanel.properties
@@ -21,5 +21,3 @@
not.loading=Not loading?
submit=Submit
cancel=Cancel
-self.pwd.reset.success=Password successfully reset
-domain=Domain
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfPasswordReset$SelfPwdResetPanel_fr_CA.properties
similarity index 92%
copy from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel.properties
copy to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfPasswordReset$SelfPwdResetPanel_fr_CA.properties
index 3779b77..73ca456 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfPasswordReset$SelfPwdResetPanel_fr_CA.properties
@@ -21,5 +21,3 @@
not.loading=Not loading?
submit=Submit
cancel=Cancel
-self.pwd.reset.success=Password successfully reset
-domain=Domain
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel_it.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfPasswordReset$SelfPwdResetPanel_it.properties
similarity index 91%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel_it.properties
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfPasswordReset$SelfPwdResetPanel_it.properties
index 5519bc4..5cc8c26 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel_it.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfPasswordReset$SelfPwdResetPanel_it.properties
@@ -21,5 +21,3 @@
not.loading=Non carica?
submit=Salva
cancel=Annulla
-self.pwd.reset.success=La password \u00e8 stata resettata con successo
-domain=Dominio
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel_ja.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfPasswordReset$SelfPwdResetPanel_ja.properties
similarity index 88%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel_ja.properties
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfPasswordReset$SelfPwdResetPanel_ja.properties
index 1e7f25d..54ca2b3 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel_ja.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfPasswordReset$SelfPwdResetPanel_ja.properties
@@ -21,5 +21,3 @@
not.loading=\u30ed\u30fc\u30c9\u3057\u3066\u3044\u307e\u305b\u3093\u304b\uff1f
submit=\u63d0\u51fa\u3059\u308b
cancel=\u30ad\u30e3\u30f3\u30bb\u30eb
-self.pwd.reset.success=\u30d1\u30b9\u30ef\u30fc\u30c9\u3092\u30ea\u30bb\u30c3\u30c8\u3057\u307e\u3057\u305f
-domain=\u30c9\u30e1\u30a4\u30f3
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel_pt_BR.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfPasswordReset$SelfPwdResetPanel_pt_BR.properties
similarity index 93%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel_pt_BR.properties
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfPasswordReset$SelfPwdResetPanel_pt_BR.properties
index cf3ca73..0a1b647 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel_pt_BR.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfPasswordReset$SelfPwdResetPanel_pt_BR.properties
@@ -21,5 +21,3 @@
not.loading=N\u00e3o est\u00e1 carregando?
submit=Enviar
cancel=Cancelar
-self.pwd.reset.success=Senha redefinida com sucesso
-domain=Domain
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel_ru.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfPasswordReset$SelfPwdResetPanel_ru.properties
similarity index 89%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel_ru.properties
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfPasswordReset$SelfPwdResetPanel_ru.properties
index 4156330..9287f49 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel_ru.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfPasswordReset$SelfPwdResetPanel_ru.properties
@@ -21,5 +21,3 @@
not.loading=\u041d\u0435 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442\u0441\u044f?
submit=\u041e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c
cancel=\u043e\u0442\u043c\u0435\u043d\u0438\u0442\u044c
-self.pwd.reset.success=\u041f\u0430\u0440\u043e\u043b\u044c \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0441\u0431\u0440\u043e\u0448\u0435\u043d
-domain=Domain
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfPasswordReset.html b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfPasswordReset.html
index 4442e79..2e5c7a2 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfPasswordReset.html
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfPasswordReset.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
@@ -18,12 +19,17 @@
-->
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
<wicket:extend>
-
+ <div class="brand-link bg-red brand-custom">
+ <span class="logo-mini">
+ <img aria-label="Apache Syncope Enduser" alt="Apache Syncope Enduser" src="ui-commons/img/logo-mini.png"/>
+ </span>
+ <span class="brand-text font-weight-light">Apache Syncope</span>
+ </div>
<section class="content" wicket:id="content">
- <div id="password_reset" class="container-fluid password_reset_wrapper">
+ <div class="box">
+ <div id="password_reset" class="container-fluid password_reset_wrapper">
- <div class="row">
- <div class="col-md-6 col-md-offset-3">
+ <div class="col-md-6 mx-auto">
<div class="page-header">
<h1>
@@ -31,14 +37,21 @@
</h1>
</div>
- <form wicket:id="selfPwdResetForm" class="form-horizontal">
- <div wicket:id="selfPwdResetPanel"/>
- </form>
+ <form wicket:id="selfPwdResetForm">
+ <div class="box-body">
+ <span wicket:id="selfPasswordResetPanelCard">[PASSWORD_RESET]</span>
+ </div>
+ <div class="password_reset_buttons form-group">
+ <input wicket:id="cancel" type="submit" wicket:message="value:cancel"
+ class="btn btn-default float-left"/>
+ <input wicket:id="submit" type="submit" wicket:message="value:submit"
+ class="btn btn-success float-right"/>
+ </div>
+ </form>
</div> <!-- col -->
- </div> <!-- row -->
+ </div>
</div>
</section>
-
</wicket:extend>
-</html>
\ No newline at end of file
+</html>
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfPasswordReset.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfPasswordReset.properties
index e76af19..3c4818e 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfPasswordReset.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfPasswordReset.properties
@@ -15,3 +15,7 @@
# specific language governing permissions and limitations
# under the License.
password-reset=Password reset
+self.pwd.reset.success=Your password has been reset successfully!
+self.pwd.reset.success.msg=An email has been sent to your address.
+self.pwd.reset.error=Error during password reset!
+self.pwd.reset.error.msg=Try again or contact an administrator.
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel_pt_BR.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfPasswordReset_fr_CA.properties
similarity index 73%
copy from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel_pt_BR.properties
copy to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfPasswordReset_fr_CA.properties
index cf3ca73..3c4818e 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel_pt_BR.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfPasswordReset_fr_CA.properties
@@ -14,12 +14,8 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-username=Nome de usu\u00e1rio\n
-securityQuestion=Pergunta de Seguran\u00e7a
-securityAnswer=Resposta de seguran\u00e7a
-reload=recarregar
-not.loading=N\u00e3o est\u00e1 carregando?
-submit=Enviar
-cancel=Cancelar
-self.pwd.reset.success=Senha redefinida com sucesso
-domain=Domain
+password-reset=Password reset
+self.pwd.reset.success=Your password has been reset successfully!
+self.pwd.reset.success.msg=An email has been sent to your address.
+self.pwd.reset.error=Error during password reset!
+self.pwd.reset.error.msg=Try again or contact an administrator.
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfPasswordReset_it.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfPasswordReset_it.properties
index 689e50a..c8a9683 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfPasswordReset_it.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfPasswordReset_it.properties
@@ -15,3 +15,7 @@
# specific language governing permissions and limitations
# under the License.
password-reset=Reset della password
+self.pwd.reset.success=La password \u00e8 stata resettata con successo
+self.pwd.reset.success.msg=Una email \u00e8 stata inviata all'indirizzo configurato
+self.pwd.reset.error=Error during password reset!
+self.pwd.reset.error.msg=Try again or contact an administrator.
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfPasswordReset_ja.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfPasswordReset_ja.properties
index ddf5e73..791121e 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfPasswordReset_ja.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfPasswordReset_ja.properties
@@ -15,3 +15,7 @@
# specific language governing permissions and limitations
# under the License.
password-reset=\u30d1\u30b9\u30ef\u30fc\u30c9\u306e\u30ea\u30bb\u30c3\u30c8
+self.pwd.reset.success=\u30d1\u30b9\u30ef\u30fc\u30c9\u3092\u30ea\u30bb\u30c3\u30c8\u3057\u307e\u3057\u305f
+self.pwd.reset.success.msg=An email has been sent to your address.
+self.pwd.reset.error=Error during password reset!
+self.pwd.reset.error.msg=Try again or contact an administrator.
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfPasswordReset_pt_BR.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfPasswordReset_pt_BR.properties
index 2163279..7195575 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfPasswordReset_pt_BR.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfPasswordReset_pt_BR.properties
@@ -15,3 +15,7 @@
# specific language governing permissions and limitations
# under the License.
password-reset=Resetar a senha
+self.pwd.reset.success=Senha redefinida com sucesso
+self.pwd.reset.success.msg=An email has been sent to your address.
+self.pwd.reset.error=Error during password reset!
+self.pwd.reset.error.msg=Try again or contact an administrator.
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfPasswordReset_ru.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfPasswordReset_ru.properties
index 2d8ab11..2bc9d14 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfPasswordReset_ru.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfPasswordReset_ru.properties
@@ -15,3 +15,7 @@
# specific language governing permissions and limitations
# under the License.
password-reset=\u0412\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u0430\u0440\u043e\u043b\u044f
+self.pwd.reset.success=\u041f\u0430\u0440\u043e\u043b\u044c \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0441\u0431\u0440\u043e\u0448\u0435\u043d
+self.pwd.reset.success.msg=An email has been sent to your address.
+self.pwd.reset.error=Error during password reset!
+self.pwd.reset.error.msg=Try again or contact an administrator.
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfRegistration.html b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfRegistration.html
new file mode 100644
index 0000000..2002cca
--- /dev/null
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfRegistration.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!--
+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.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
+ <wicket:extend>
+ <div class="brand-link bg-red brand-custom">
+ <span class="logo-mini">
+ <img aria-label="Apache Syncope Enduser" alt="Apache Syncope Enduser" src="ui-commons/img/logo-mini.png"/>
+ </span>
+ <span class="brand-text font-weight-light">Apache Syncope</span>
+ </div>
+ <section class="content" wicket:id="content">
+ <div class="row clearfix">
+ <!-- left column -->
+ <div class="col-md-12">
+ <div class="col-md-12 column box">
+ <span wicket:id="selfRegistrationPanel"></span>
+ </div>
+ </div>
+ </div>
+ </section>
+ </wicket:extend>
+</html>
+X
\ No newline at end of file
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfResult.html b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfResult.html
new file mode 100644
index 0000000..19e5d56
--- /dev/null
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfResult.html
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<!--
+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.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
+ <wicket:extend>
+ <div class="brand-link bg-red brand-custom">
+ <span class="logo-mini">
+ <img aria-label="Apache Syncope Enduser" alt="Apache Syncope Enduser" src="ui-commons/img/logo-mini.png"/>
+ </span>
+ <span class="brand-text font-weight-light">Apache Syncope</span>
+ </div>
+ <section class="content" wicket:id="content">
+ <div class="box">
+ <div id="password_reset" class="container-fluid password_reset_wrapper">
+
+ <div class="row ">
+ <div class="col-md-6 mx-auto">
+
+ <div class="page-header">
+ <h1>
+ <span wicket:id="resultTitle">[LABEL]</span>
+ </h1>
+
+ </div>
+ <fieldset class="enduser_fieldset">
+
+ <div class="form-group input-md">
+ <span wicket:id="resultMessage">[LABEL]</span>
+ <a wicket:id="login">
+ <wicket:message key="login">[login]</wicket:message>
+ </a>
+ </div>
+
+ </fieldset>
+
+ <span wicket:id="statusIcon"></span>
+ <wicket:fragment wicket:id="successIcon">
+ <svg class="checkmark_ok" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 52 52">
+ <circle class="checkmark_circle_ok" cx="26" cy="26" r="25" fill="none"/>
+ <path class="checkmark_check_ok" fill="none" d="M14.1 27.2l7.1 7.2 16.7-16.8"/>
+ </svg>
+ </wicket:fragment>
+ <wicket:fragment wicket:id="errorIcon">
+ <svg class="checkmark_error" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 52 52">
+ <circle class="checkmark_circle_error" cx="26" cy="26" r="25" fill="none"/>
+ <path class="checkmark_check_error" fill="none" d="M16 16 36 36 M36 16 16 36"/>
+ </svg>
+ </wicket:fragment>
+
+
+ </div>
+ </div> <!-- col -->
+ </div> <!-- row -->
+ </div>
+ </section>
+
+ </wicket:extend>
+</html>
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfResult.properties
similarity index 94%
copy from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties
copy to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfResult.properties
index 56c00af..bcdb339 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfResult.properties
@@ -14,4 +14,4 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-auxClasses.palette=Auxiliary classes
+login=Back to Home
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfResult_fr_CA.properties
similarity index 94%
copy from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties
copy to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfResult_fr_CA.properties
index 56c00af..bcdb339 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfResult_fr_CA.properties
@@ -14,4 +14,4 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-auxClasses.palette=Auxiliary classes
+login=Back to Home
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfResult_it.properties
similarity index 94%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfResult_it.properties
index 56c00af..709cc6f 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfResult_it.properties
@@ -14,4 +14,4 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-auxClasses.palette=Auxiliary classes
+login=Torna alla Home
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfResult_ja.properties
similarity index 94%
copy from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties
copy to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfResult_ja.properties
index 56c00af..bcdb339 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfResult_ja.properties
@@ -14,4 +14,4 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-auxClasses.palette=Auxiliary classes
+login=Back to Home
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfResult_pt_BR.properties
similarity index 94%
copy from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties
copy to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfResult_pt_BR.properties
index 56c00af..bcdb339 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfResult_pt_BR.properties
@@ -14,4 +14,4 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-auxClasses.palette=Auxiliary classes
+login=Back to Home
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfResult_ru.properties
similarity index 94%
copy from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties
copy to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfResult_ru.properties
index 56c00af..bcdb339 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfResult_ru.properties
@@ -14,4 +14,4 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-auxClasses.palette=Auxiliary classes
+login=Back to Home
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfUpdate.html b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfUpdate.html
index 629e25f..40638bc 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfUpdate.html
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/SelfUpdate.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/WizardMgtPanel.html b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/WizardMgtPanel.html
deleted file mode 100644
index c62d0d0..0000000
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/pages/WizardMgtPanel.html
+++ /dev/null
@@ -1,60 +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.
--->
-<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
- <wicket:panel>
- <span wicket:id="container">
- <wicket:container wicket:id="content"/>
- </span>
-
- <wicket:fragment wicket:id="wizard">
- <div class="col-xs-12">
- <div class="box">
- <div class="box-header">
- <h3 class="box-title">
- <span wicket:id="title">[TITLE]</span>
- </h3>
- </div>
- <div class="box-body">
- <span wicket:id="wizard"/>
- </div>
- </div>
- </div>
- </wicket:fragment>
-
- <wicket:fragment wicket:id="default">
-
- <wicket:child/>
-
- <wicket:enclosure child="add">
- <div class="modal-footer">
- <a href="#" class="btn btn-default btn-circle btn-lg float-left" wicket:id="exit">
- <i class="fas fa-sign-out-alt"></i>
- </a>
- <a href="#" class="btn btn-success btn-circle btn-lg" wicket:id="add">
- <i class="fa fa-plus"></i>
- </a>
- </div>
- </wicket:enclosure>
- </wicket:fragment>
-
- <span wicket:id="outerObjectsRepeater">
- <div wicket:id="outer"/>
- </span>
- </wicket:panel>
-</html>
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/ChangePasswordPanel.html b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/ChangePasswordPanel.html
new file mode 100644
index 0000000..a31ec8b
--- /dev/null
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/ChangePasswordPanel.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<!--
+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.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
+ <wicket:panel>
+ <div class="row clearfix">
+ <!-- left column -->
+ <div class="col-md-12">
+ <div class="col-md-6 mx-auto">
+ <!-- form start -->
+ <form wicket:id="changePassword" class="form-horizontal">
+ <div class="box-body">
+ <div class="box-header formcard">
+ <header class="card-container bg-danger">
+ <label class="card-header-style"><wicket:message key="editchangepassword"/></label>
+ </header>
+ <div class="card-container-body">
+ <div>
+ <div class="col-xs-12">
+ <div class="form-group">
+ <span id="password" wicket:id="password"/>
+ </div>
+ <div class="form-group">
+ <span id="confirmPassword" wicket:id="confirmPassword"/>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <span wicket:id="captchaPanelCard"/>
+ </div>
+ <div class="box-footer">
+ <input id="submit_button" wicket:id="submit" type="submit" wicket:message="value:submit"
+ class="btn btn-success float-right"/>
+ <input id="cancel_button" wicket:id="cancel" type="submit" wicket:message="value:cancel"
+ class="btn btn-default float-left"/>
+ </div>
+ </form>
+ <!-- /.box-body -->
+ </div>
+ </div>
+ </div><!-- </div> -->
+ </wicket:panel>
+</html>
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/ChangePasswordPanel.properties
similarity index 79%
copy from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel.properties
copy to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/ChangePasswordPanel.properties
index 3779b77..f2447ea 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/ChangePasswordPanel.properties
@@ -15,11 +15,10 @@
# specific language governing permissions and limitations
# under the License.
username=Username
-securityQuestion=Security Question
-securityAnswer=Security Answer
-reload=Reload
-not.loading=Not loading?
-submit=Submit
+password=Password
+submit=Change
cancel=Cancel
-self.pwd.reset.success=Password successfully reset
-domain=Domain
+confirmPassword=Password (confirm)
+passwordNeedsToBeUpdated=Password needs to be updated
+self.pwd.change.success=Password successfully changed
+editchangepassword=Change password
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/ChangePasswordPanel_it.properties
similarity index 79%
copy from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel.properties
copy to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/ChangePasswordPanel_it.properties
index 3779b77..0d65dc4 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/ChangePasswordPanel_it.properties
@@ -15,11 +15,10 @@
# specific language governing permissions and limitations
# under the License.
username=Username
-securityQuestion=Security Question
-securityAnswer=Security Answer
-reload=Reload
-not.loading=Not loading?
-submit=Submit
-cancel=Cancel
-self.pwd.reset.success=Password successfully reset
-domain=Domain
+password=Password
+submit=Cambia
+cancel=Annulla
+confirmPassword=Password (conferma)
+passwordNeedsToBeUpdated=La password deve essere aggiornata
+self.pwd.change.success=Password aggiornata con successo
+
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel_ja.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/ChangePasswordPanel_ja.properties
similarity index 68%
copy from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel_ja.properties
copy to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/ChangePasswordPanel_ja.properties
index 1e7f25d..34bb07c 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel_ja.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/ChangePasswordPanel_ja.properties
@@ -15,11 +15,10 @@
# specific language governing permissions and limitations
# under the License.
username=\u30e6\u30fc\u30b6\u30fc\u540d
-securityQuestion=\u79d8\u5bc6\u306e\u8cea\u554f
-securityAnswer=\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3\u56de\u7b54
-reload=\u30ea\u30ed\u30fc\u30c9
-not.loading=\u30ed\u30fc\u30c9\u3057\u3066\u3044\u307e\u305b\u3093\u304b\uff1f
-submit=\u63d0\u51fa\u3059\u308b
+password=\u30d1\u30b9\u30ef\u30fc\u30c9
+submit=\u5909\u66f4
cancel=\u30ad\u30e3\u30f3\u30bb\u30eb
-self.pwd.reset.success=\u30d1\u30b9\u30ef\u30fc\u30c9\u3092\u30ea\u30bb\u30c3\u30c8\u3057\u307e\u3057\u305f
-domain=\u30c9\u30e1\u30a4\u30f3
+confirmPassword=\u30d1\u30b9\u30ef\u30fc\u30c9 (\u78ba\u8a8d)
+passwordNeedsToBeUpdated=\u30d1\u30b9\u30ef\u30fc\u30c9\u3092\u66f4\u65b0\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059
+self.pwd.change.success=\u30d1\u30b9\u30ef\u30fc\u30c9\u304c\u6b63\u5e38\u306b\u5909\u66f4\u3055\u308c\u307e\u3057\u305f
+
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/ChangePasswordPanel_pt_BR.properties
similarity index 78%
copy from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel.properties
copy to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/ChangePasswordPanel_pt_BR.properties
index 3779b77..3390349 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/ChangePasswordPanel_pt_BR.properties
@@ -14,12 +14,11 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-username=Username
-securityQuestion=Security Question
-securityAnswer=Security Answer
-reload=Reload
-not.loading=Not loading?
-submit=Submit
-cancel=Cancel
-self.pwd.reset.success=Password successfully reset
-domain=Domain
+username=Usu\u00e1rio
+password=Senha
+submit=Alterar
+Cancel=Cancelar
+confirmPassword=Senha (confirmar)
+passwordNeedsToBeUpdated=Senha precisa ser atualizado
+self.pwd.change.success=Senha mudada com sucesso
+
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/ChangePasswordPanel_ru.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/ChangePasswordPanel_ru.properties
new file mode 100644
index 0000000..6f199c6
--- /dev/null
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/ChangePasswordPanel_ru.properties
@@ -0,0 +1,28 @@
+# 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.
+username=\u0418\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f
+# password=\u00d0\u009f\u00d0\u00b0\u00d1\u0080\u00d0\u00be\u00d0\u00bb\u00d1\u008c
+password=\u041f\u0430\u0440\u043e\u043b\u044c
+# submit=\u00d0\u0098\u00d0\u00b7\u00d0\u00bc\u00d0\u00b5\u00d0\u00bd\u00d0\u00b8\u00d1\u0082\u00d1\u008c
+submit=\u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c
+cancel=\u043e\u0442\u043c\u0435\u043d\u0438\u0442\u044c
+#confirmPassword=\u00d0\u009f\u00d0\u00b0\u00d1\u0080\u00d0\u00be\u00d0\u00bb\u00d1\u008c (\u00d0\u00bf\u00d0\u00be\u00d0\u00b4\u00d1\u0082\u00d0\u00b2\u00d0\u00b5\u00d1\u0080\u00d0\u00b6\u00d0\u00b4\u00d0\u00b5\u00d0\u00bd\u00d0\u00b8\u00d0\u00b5)
+confirmPassword=\u041f\u0430\u0440\u043e\u043b\u044c (\u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435)
+# passwordNeedsToBeUpdated=\u00d0\u009f\u00d0\u00b0\u00d1\u0080\u00d0\u00be\u00d0\u00bb\u00d1\u008c \u00d0\u00b4\u00d0\u00be\u00d0\u00bb\u00d0\u00b6\u00d0\u00b5\u00d0\u00bd \u00d0\u00b1\u00d1\u008b\u00d1\u0082\u00d1\u008c \u00d0\u00b8\u00d0\u00b7\u00d0\u00bc\u00d0\u00b5\u00d0\u00bd\u00d1\u0091\u00d0\u00bd
+passwordNeedsToBeUpdated=\u041f\u0430\u0440\u043e\u043b\u044c \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0451\u043d
+self.pwd.change.success=\u041f\u0430\u0440\u043e\u043b\u044c \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0438\u0437\u043c\u0435\u043d\u0435\u043d
+
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/Sidebar.html b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/Sidebar.html
new file mode 100644
index 0000000..36bd619
--- /dev/null
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/Sidebar.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<!--
+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.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
+ <wicket:panel>
+ <div class="brand-link bg-red" style="height: 57px;">
+ <span style="position: absolute;">
+ <img src="ui-commons/img/logo-mini.png" alt="Apache Syncope Logo" class="brand-image" style="max-height: none; opacity: .8;"/>
+ <span class="brand-text font-weight-light">Apache Syncope</span>
+ </span>
+ </div>
+
+ <!-- Sidebar -->
+ <div class="sidebar">
+ <div class="user-panel mt-2 pb-2 mb-2 d-flex">
+ </div>
+
+ <!-- Sidebar Menu -->
+ <nav class="mt-2">
+ <ul class="nav nav-pills nav-sidebar flex-column nav-child-indent nav-compact" data-widget="treeview" role="menu" data-accordion="false">
+ <li class="nav-item" wicket:id="dashboardLI"><a href="#" wicket:id="home" class="nav-link"><i class="fa fa-id-card nav-icon"></i><p><wicket:message key="home"/></p></a></li>
+ <li wicket:id="profileLI" class="nav-item has-treeview">
+ <a id="profileLink" href="#" class="nav-link"><i class="nav-icon fa fa-user"></i><p><wicket:message key="profile"/></p> <i class="fas fa-angle-left right"></i></a>
+ <ul wicket:id="profileUL" class="nav nav-treeview">
+ <li class="nav-item" wicket:id="edituserLI"><a href="#" class="nav-link" wicket:id="edituser"><i class="nav-icon fa fa-edit"></i><p><wicket:message key="edituser"/></p></a></li>
+ <li class="nav-item" wicket:id="editchangepasswordLI"><a href="#" class="nav-link" wicket:id="editchangepassword"><i class="nav-icon fas fa-key"></i><p><wicket:message key="editchangepassword"/></p></a></li>
+ <li class="nav-item" wicket:id="editsecurityquestionLI"><a href="#" class="nav-link" wicket:id="editsecurityquestion"><i class="nav-icon fa fa-lock"></i><p><wicket:message key="editsecurityquestion"/></p></a></li>
+ </ul>
+ </li>
+
+ <wicket:container wicket:id="extPages">
+ <li class="nav-item" wicket:id="extPageLI">
+ <a href="#" class="nav-link" wicket:id="extPage"><i wicket:id="extPageIcon"></i><p wicket:id="extPageLabel"/></a>
+ </li>
+ </wicket:container>
+ </ul>
+ </nav>
+ <!-- /.sidebar-menu -->
+ </div>
+ <!-- /.sidebar -->
+ </wicket:panel>
+</html>
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/UserFormPanel.html b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/UserFormPanel.html
new file mode 100644
index 0000000..1f80dab
--- /dev/null
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/UserFormPanel.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<!--
+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.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml" >
+ <wicket:panel>
+ <!-- general form elements -->
+ <div class="col-md-6 mx-auto">
+ <!-- form start -->
+ <form wicket:id="form">
+ <div class="box-body">
+ <span wicket:id="userDetailsPanelCard">[userDetailsPanelCard]</span>
+ <span wicket:id="groupsPanelCard">[groupsPanelCard]</span>
+ <span wicket:id="plainAttrsPanelCard">[plainAttrsPanelCard]</span>
+ <span wicket:id="derAttrsPanelCard">[derAttrsPanelCard]</span>
+ <span wicket:id="virAttrsPanelCard">[virAttrsPanelCard]</span>
+ <span wicket:id="resourcesPanelCard">[resourcesPanelCard]</span>
+ <span wicket:id="captchaPanelCard">[captchaPanelCard]</span>
+ </div>
+ <!-- /.box-body -->
+ <div class="box-footer">
+ <input id="submit_button" wicket:id="submit" type="submit" wicket:message="value:submit"
+ class="btn btn-success float-right"/>
+ <input id="cancel_button" wicket:id="cancel" type="submit" wicket:message="value:cancel"
+ class="btn btn-default float-left"/>
+ </div>
+ </form>
+ </div>
+ </wicket:panel>
+</html>
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/UserFormPanel.properties
similarity index 77%
copy from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel.properties
copy to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/UserFormPanel.properties
index 3779b77..0a7e6bb 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/UserFormPanel.properties
@@ -14,12 +14,8 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-username=Username
-securityQuestion=Security Question
-securityAnswer=Security Answer
-reload=Reload
-not.loading=Not loading?
-submit=Submit
-cancel=Cancel
-self.pwd.reset.success=Password successfully reset
-domain=Domain
+self.profile.change.success.msg=Your profile has been successfully changed
+
+self.profile.change.success=Operation completed successfully
+self.profile.change.error.msg=Error updating profile
+self.profile.change.error=Error
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/UserFormPanel_it.properties
similarity index 75%
copy from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel.properties
copy to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/UserFormPanel_it.properties
index 3779b77..94cf2b2 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/UserFormPanel_it.properties
@@ -14,12 +14,7 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-username=Username
-securityQuestion=Security Question
-securityAnswer=Security Answer
-reload=Reload
-not.loading=Not loading?
-submit=Submit
-cancel=Cancel
-self.pwd.reset.success=Password successfully reset
-domain=Domain
+self.profile.change.success.msg=Il tuo profilo \u00e8 stato modificato correttamente
+self.profile.change.success=Operazione completata con successo
+self.profile.change.error.msg=Errore durante l'aggiornamento del profilo
+self.profile.change.error=Errore
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel_pt_BR.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/UserFormPanel_ja.properties
similarity index 64%
copy from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel_pt_BR.properties
copy to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/UserFormPanel_ja.properties
index cf3ca73..6bfaa27 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel_pt_BR.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/UserFormPanel_ja.properties
@@ -14,12 +14,7 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-username=Nome de usu\u00e1rio\n
-securityQuestion=Pergunta de Seguran\u00e7a
-securityAnswer=Resposta de seguran\u00e7a
-reload=recarregar
-not.loading=N\u00e3o est\u00e1 carregando?
-submit=Enviar
-cancel=Cancelar
-self.pwd.reset.success=Senha redefinida com sucesso
-domain=Domain
+self.profile.change.success.msg=\u30d7\u30ed\u30d5\u30a1\u30a4\u30eb\u304c\u6b63\u5e38\u306b\u7de8\u96c6\u3055\u308c\u307e\u3057\u305f
+self.profile.change.success=\u64cd\u4f5c\u306f\u6b63\u5e38\u306b\u5b8c\u4e86\u3057\u307e\u3057\u305f
+self.profile.change.error.msg=\u30d7\u30ed\u30d5\u30a1\u30a4\u30eb\u306e\u66f4\u65b0\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f
+self.profile.change.error=\u30a8\u30e9\u30fc
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/UserFormPanel_pt_BR.properties
similarity index 77%
copy from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel.properties
copy to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/UserFormPanel_pt_BR.properties
index 3779b77..fda623b 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/UserFormPanel_pt_BR.properties
@@ -14,12 +14,7 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-username=Username
-securityQuestion=Security Question
-securityAnswer=Security Answer
-reload=Reload
-not.loading=Not loading?
-submit=Submit
-cancel=Cancel
-self.pwd.reset.success=Password successfully reset
-domain=Domain
+self.profile.change.success.msg=Seu perfil foi editado com sucesso
+self.profile.change.success=Opera\u00e7\u00e3o conclu\u00edda com sucesso
+self.profile.change.error.msg=Erro ao atualizar perfil
+self.profile.change.error=Erro
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/UserFormPanel_ru.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/UserFormPanel_ru.properties
new file mode 100644
index 0000000..adc4bf8
--- /dev/null
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/UserFormPanel_ru.properties
@@ -0,0 +1,20 @@
+# 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.
+self.profile.change.success.msg=\u0412\u0430\u0448 \u043f\u0440\u043e\u0444\u0438\u043b\u044c \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u043e\u0442\u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d
+self.profile.change.success=\u041e\u043f\u0435\u0440\u0430\u0446\u0438\u044f \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0430
+self.profile.change.error.msg=\u041e\u0448\u0438\u0431\u043a\u0430 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0444\u0438\u043b\u044f
+self.profile.change.error=\u043e\u0448\u0438\u0431\u043a\u0430
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/AbstractAttrs$Schemas.html b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/AbstractAttrs$Schemas.html
similarity index 98%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/AbstractAttrs$Schemas.html
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/AbstractAttrs$Schemas.html
index f62795a..ab664f9 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/AbstractAttrs$Schemas.html
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/AbstractAttrs$Schemas.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/AbstractAttrs.html b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/AbstractAttrs.html
similarity index 98%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/AbstractAttrs.html
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/AbstractAttrs.html
index 435b727..41b83c5 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/AbstractAttrs.html
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/AbstractAttrs.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/AbstractAttrs.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/AbstractAttrs.properties
similarity index 100%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/AbstractAttrs.properties
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/AbstractAttrs.properties
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/AbstractAttrs_it.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/AbstractAttrs_it.properties
similarity index 100%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/AbstractAttrs_it.properties
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/AbstractAttrs_it.properties
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/AbstractAttrs_ja.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/AbstractAttrs_ja.properties
similarity index 100%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/AbstractAttrs_ja.properties
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/AbstractAttrs_ja.properties
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/AbstractAttrs_pt_BR.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/AbstractAttrs_pt_BR.properties
similarity index 100%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/AbstractAttrs_pt_BR.properties
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/AbstractAttrs_pt_BR.properties
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/AbstractAttrs_ru.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/AbstractAttrs_ru.properties
similarity index 99%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/AbstractAttrs_ru.properties
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/AbstractAttrs_ru.properties
index b28194c..691a2c5 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/AbstractAttrs_ru.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/AbstractAttrs_ru.properties
@@ -14,6 +14,5 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-#
attributes.accordion=\u0421\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0435
attributes.membership.accordion=\u0418\u0437 \u0443\u0447\u0430\u0441\u0442\u043d\u0438\u043a\u043e\u0432 \u0433\u0440\u0443\u043f\u043f\u044b '${groupName}'
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/DerAttrs.html b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/DerAttrs.html
similarity index 98%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/DerAttrs.html
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/DerAttrs.html
index dfcda58..0e0fec9 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/DerAttrs.html
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/DerAttrs.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/DerAttrs.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/DerAttrs.properties
similarity index 100%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/DerAttrs.properties
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/DerAttrs.properties
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/DerAttrs_it.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/DerAttrs_it.properties
similarity index 100%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/DerAttrs_it.properties
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/DerAttrs_it.properties
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/DerAttrs_ja.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/DerAttrs_ja.properties
similarity index 100%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/DerAttrs_ja.properties
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/DerAttrs_ja.properties
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/DerAttrs_pt_BR.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/DerAttrs_pt_BR.properties
similarity index 100%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/DerAttrs_pt_BR.properties
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/DerAttrs_pt_BR.properties
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/DerAttrs_ru.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/DerAttrs_ru.properties
similarity index 99%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/DerAttrs_ru.properties
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/DerAttrs_ru.properties
index 3266270..64927a7 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/DerAttrs_ru.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/DerAttrs_ru.properties
@@ -14,7 +14,6 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-#
derived.emptyvalue.message=\u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043e...
attribute.empty.list=\u041d\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0445 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u043d\u044b\u0445 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432
attributes.derived=\u041f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u043d\u044b\u0435 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/Groups.html b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/Groups.html
similarity index 88%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/Groups.html
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/Groups.html
index 1a505db..4f3d614 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/Groups.html
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/Groups.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
@@ -19,11 +20,8 @@
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
<wicket:panel>
<div class="col-xs-12" wicket:id="groupsContainer">
- <div class="box">
+ <div>
<div class="box-header">
- <h3 class="box-title">
- <wicket:message key="groups.palette">[GROUPS]</wicket:message>
- </h3>
<span wicket:id="changed"></span>
</div>
<div class="box-body">
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/Groups.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/Groups.properties
similarity index 100%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/Groups.properties
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/Groups.properties
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/Groups_it.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/Groups_it.properties
similarity index 100%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/Groups_it.properties
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/Groups_it.properties
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/Groups_ja.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/Groups_ja.properties
similarity index 100%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/Groups_ja.properties
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/Groups_ja.properties
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/Groups_pt_BR.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/Groups_pt_BR.properties
similarity index 100%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/Groups_pt_BR.properties
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/Groups_pt_BR.properties
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/Groups_ru.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/Groups_ru.properties
similarity index 99%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/Groups_ru.properties
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/Groups_ru.properties
index 72a0042..0a348ec 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/Groups_ru.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/Groups_ru.properties
@@ -14,6 +14,5 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-#
groups.palette=\u0413\u0440\u0443\u043f\u043f\u044b
palette.available=Available (limited to the first 30 results)
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/PlainAttrs.html b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/PlainAttrs.html
similarity index 93%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/PlainAttrs.html
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/PlainAttrs.html
index 8da9bd9..9650ce5 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/PlainAttrs.html
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/PlainAttrs.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
@@ -20,7 +21,7 @@
<wicket:extend>
<div wicket:id="plainSchemas"/>
<span wicket:id="membershipsPlainSchemas">
- <div wicket:id="membershipPlainSchemas"/>
+ <div wicket:id="membershipPlainSchemas"/>
</span>
</wicket:extend>
</html>
\ No newline at end of file
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/PlainAttrs.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/PlainAttrs.properties
similarity index 100%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/PlainAttrs.properties
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/PlainAttrs.properties
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/PlainAttrs_it.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/PlainAttrs_it.properties
similarity index 100%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/PlainAttrs_it.properties
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/PlainAttrs_it.properties
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/PlainAttrs_ja.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/PlainAttrs_ja.properties
similarity index 100%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/PlainAttrs_ja.properties
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/PlainAttrs_ja.properties
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/PlainAttrs_pt_BR.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/PlainAttrs_pt_BR.properties
similarity index 100%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/PlainAttrs_pt_BR.properties
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/PlainAttrs_pt_BR.properties
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/PlainAttrs_ru.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/PlainAttrs_ru.properties
similarity index 99%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/PlainAttrs_ru.properties
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/PlainAttrs_ru.properties
index c073f72..77d39fe 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/PlainAttrs_ru.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/PlainAttrs_ru.properties
@@ -14,6 +14,5 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-#
attribute.empty.list=\u041f\u0440\u043e\u0441\u0442\u044b\u0435 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0442
attributes.plain=\u041f\u0440\u043e\u0441\u0442\u044b\u0435 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/Resources.html b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/Resources.html
similarity index 88%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/Resources.html
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/Resources.html
index 10f17f7..042f47f 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/Resources.html
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/Resources.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
@@ -19,11 +20,8 @@
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
<wicket:panel>
<div class="col-xs-12">
- <div class="box">
+ <div>
<div class="box-header">
- <h3 class="box-title">
- <wicket:message key="resources.palette">[ROLES]</wicket:message>
- </h3>
<span wicket:id="changed"></span>
</div>
<div class="box-body">
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/Resources.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/Resources.properties
similarity index 100%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/Resources.properties
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/Resources.properties
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/Resources_it.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/Resources_it.properties
similarity index 100%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/Resources_it.properties
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/Resources_it.properties
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/Resources_ja.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/Resources_ja.properties
similarity index 100%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/Resources_ja.properties
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/Resources_ja.properties
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/Resources_pt_BR.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/Resources_pt_BR.properties
similarity index 100%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/Resources_pt_BR.properties
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/Resources_pt_BR.properties
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/Resources_ru.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/Resources_ru.properties
similarity index 94%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/Resources_ru.properties
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/Resources_ru.properties
index 8e75558..ce0edc1 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/Resources_ru.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/Resources_ru.properties
@@ -14,6 +14,4 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-
-# resources.palette=Внешние ресурсы
resources.palette=\u0412\u043d\u0435\u0448\u043d\u0438\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u044b
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/DerAttrs.html b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/SelfUserDetails.html
similarity index 86%
copy from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/DerAttrs.html
copy to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/SelfUserDetails.html
index dfcda58..ca2c857 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/DerAttrs.html
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/SelfUserDetails.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
@@ -18,9 +19,6 @@
-->
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
<wicket:extend>
- <div wicket:id="derSchemas"/>
- <span wicket:id="membershipsDerSchemas">
- <div wicket:id="membershipDerSchemas"/>
- </span>
+ <div wicket:id="password"></div>
</wicket:extend>
-</html>
\ No newline at end of file
+</html>
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/UserDetails$EditUserPasswordPanel.html b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/UserDetails$EditUserPasswordPanel.html
similarity index 90%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/UserDetails$EditUserPasswordPanel.html
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/UserDetails$EditUserPasswordPanel.html
index e77ed5d..380233c 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/UserDetails$EditUserPasswordPanel.html
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/UserDetails$EditUserPasswordPanel.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
@@ -20,7 +21,7 @@
<wicket:panel>
<div id="editUserChangePassword">
<div class="alert alert-warning">
- <i class="fas fa-exclamation-triangle"></i> <label wicket:id="warning">[warning]</label>
+ <i class="fa fa-exclamation-triangle"></i> <label wicket:id="warning">[warning]</label>
</div>
<div wicket:id="passwordPanel">[change password panel]</div>
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/UserDetails.html b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/UserDetails.html
similarity index 80%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/UserDetails.html
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/UserDetails.html
index cc02ba2..3773f68 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/UserDetails.html
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/UserDetails.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
@@ -25,13 +26,7 @@
<div class="form-group">
<span wicket:id="username"/>
</div>
- <div wicket:id="accordionPanel"></div>
- <div class="form-group">
- <span wicket:id="securityQuestion">[SECURITY QUESTION]</span>
- </div>
- <div class="form-group">
- <span wicket:id="securityAnswer">[SECURITY ANSWER]</span>
- </div>
+ <wicket:child/>
</div>
</wicket:panel>
</html>
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/UserDetails.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/UserDetails.properties
similarity index 100%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/UserDetails.properties
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/UserDetails.properties
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/UserDetails_it.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/UserDetails_it.properties
similarity index 100%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/UserDetails_it.properties
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/UserDetails_it.properties
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/UserDetails_ja.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/UserDetails_ja.properties
similarity index 100%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/UserDetails_ja.properties
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/UserDetails_ja.properties
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/UserDetails_pt_BR.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/UserDetails_pt_BR.properties
similarity index 100%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/UserDetails_pt_BR.properties
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/UserDetails_pt_BR.properties
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/UserDetails_ru.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/UserDetails_ru.properties
similarity index 100%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/UserDetails_ru.properties
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/UserDetails_ru.properties
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/VirAttrs.html b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/VirAttrs.html
similarity index 98%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/VirAttrs.html
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/VirAttrs.html
index abff807..5968a33 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/VirAttrs.html
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/VirAttrs.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/VirAttrs.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/VirAttrs.properties
similarity index 100%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/VirAttrs.properties
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/VirAttrs.properties
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/VirAttrs_it.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/VirAttrs_it.properties
similarity index 100%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/VirAttrs_it.properties
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/VirAttrs_it.properties
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/VirAttrs_ja.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/VirAttrs_ja.properties
similarity index 100%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/VirAttrs_ja.properties
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/VirAttrs_ja.properties
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/VirAttrs_pt_BR.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/VirAttrs_pt_BR.properties
similarity index 100%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/VirAttrs_pt_BR.properties
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/VirAttrs_pt_BR.properties
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/VirAttrs_ru.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/VirAttrs_ru.properties
similarity index 99%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/VirAttrs_ru.properties
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/VirAttrs_ru.properties
index 7509896..a162426 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/VirAttrs_ru.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/VirAttrs_ru.properties
@@ -14,6 +14,5 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-
attribute.empty.list=\u0412\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0435 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0442
attributes.virtual=\u0412\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0435 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/CaptchaPanel.html b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/captcha/CaptchaPanel.html
similarity index 84%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/CaptchaPanel.html
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/captcha/CaptchaPanel.html
index 985fc50..92dd8fb 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/CaptchaPanel.html
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/captcha/CaptchaPanel.html
@@ -24,10 +24,10 @@
<img wicket:id="image" />
</div>
<div id="captcha_image" class="captcha_elem">
- <button wicket:id="reloadButton" id="refresh" type="button" class="btn btn-default btn-xs fa fa-sync"
- title="Refresh Captcha"></button>
- <button id="infoLink" class="btn btn-default btn-xs fa fa-question-circle" title="What is this?"
- onclick="window.open('https://it.wikipedia.org/wiki/CAPTCHA')"></button>
+ <button wicket:id="reloadButton" id="refresh" type="button" class="btn btn-default btn-xs"
+ title="Refresh Captcha"><i class="fas fa-sync"></i></button>
+ <button id="infoLink" class="btn btn-default btn-xs" title="What is this?"
+ onclick="window.open('https://it.wikipedia.org/wiki/CAPTCHA')"><i class="fa fa-question-circle"></i></button>
</div>
<div>
<label for="captcha"><wicket:message key="captcha.message"/></label>
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/CaptchaPanel.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/captcha/CaptchaPanel.properties
similarity index 100%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/CaptchaPanel.properties
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/captcha/CaptchaPanel.properties
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/CaptchaPanel_it.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/captcha/CaptchaPanel_it.properties
similarity index 100%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/CaptchaPanel_it.properties
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/captcha/CaptchaPanel_it.properties
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/CaptchaPanel_ja.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/captcha/CaptchaPanel_ja.properties
similarity index 100%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/CaptchaPanel_ja.properties
rename to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/captcha/CaptchaPanel_ja.properties
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/widgets/UserProfileWidget.html b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/widgets/UserProfileWidget.html
new file mode 100644
index 0000000..71c4015
--- /dev/null
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/widgets/UserProfileWidget.html
@@ -0,0 +1,50 @@
+<!--
+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.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
+ <wicket:panel>
+ <div class="box">
+ <div class="box-body" wicket:id="userProfile">
+ <div class="box-header formcard col-md-4">
+ <header class="card-container bg-danger">
+ <label class="card-header-style">
+ <wicket:message key="welcome"/>
+ <b><label class="card-header-style" wicket:id="welcome"/></b></label>
+ </header>
+ <div class="card-container-body">
+ <div>
+ <div class="box-footer no-padding no-border-top">
+ <ul class="nav navbar-nav flex-column">
+ <li class="nav-item"><a class="nav-link disabled" href="#"><wicket:message key="name"/>:
+ <span class="float-right badge"><label wicket:id="username"/></span></a>
+ </li>
+ <li class="nav-item"><a class="nav-link disabled" href="#"><wicket:message key="lastLoginDate"/>:
+ <span class="float-right badge"><label wicket:id="lastLoginDate"/></span></a>
+ </li>
+ <li class="nav-item"><a class="nav-link disabled" href="#"><wicket:message key="lastChangePwdDate"/>:
+ <span class="float-right badge"><label wicket:id="changePwdDate"/></span></a>
+ </li>
+ </ul>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </wicket:panel>
+</html>
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/widgets/UserProfileWidget.properties
similarity index 88%
copy from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties
copy to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/widgets/UserProfileWidget.properties
index 56c00af..04eedfc 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/widgets/UserProfileWidget.properties
@@ -14,4 +14,7 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-auxClasses.palette=Auxiliary classes
+welcome=Welcome,
+name=Name
+lastLoginDate=Last Login Date
+lastChangePwdDate=Last Change Password Date
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/widgets/UserProfileWidget_fr_CA.properties
similarity index 87%
copy from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties
copy to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/widgets/UserProfileWidget_fr_CA.properties
index 56c00af..b6e20a6 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/widgets/UserProfileWidget_fr_CA.properties
@@ -14,4 +14,7 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-auxClasses.palette=Auxiliary classes
+welcome=Bienvenu,
+name=Name
+lastLoginDate=Last Login Date
+lastChangePwdDate=Last Change Password Date
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/widgets/UserProfileWidget_it.properties
similarity index 87%
copy from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties
copy to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/widgets/UserProfileWidget_it.properties
index 56c00af..a9c98ce 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/widgets/UserProfileWidget_it.properties
@@ -14,4 +14,8 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-auxClasses.palette=Auxiliary classes
+welcome=Benvenuto,
+
+name=Nome
+lastLoginDate=Data Ultimo Accesso
+lastChangePwdDate=Data Ultimo Cambio Password
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/widgets/UserProfileWidget_ja.properties
similarity index 85%
copy from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties
copy to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/widgets/UserProfileWidget_ja.properties
index 56c00af..b6154b7 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/widgets/UserProfileWidget_ja.properties
@@ -14,4 +14,8 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-auxClasses.palette=Auxiliary classes
+welcome=\u30e6\u30fc\u30b6\u30fc\u540d
+
+name=Name
+lastLoginDate=Last Login Date
+lastChangePwdDate=Last Change Password Date
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/widgets/UserProfileWidget_pt_BR.properties
similarity index 87%
copy from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties
copy to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/widgets/UserProfileWidget_pt_BR.properties
index 56c00af..64baa37 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/widgets/UserProfileWidget_pt_BR.properties
@@ -14,4 +14,8 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-auxClasses.palette=Auxiliary classes
+welcome=Bem-vinda
+
+name=Name
+lastLoginDate=Last Login Date
+lastChangePwdDate=Last Change Password Date
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/widgets/UserProfileWidget_ru.properties
similarity index 86%
copy from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties
copy to client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/widgets/UserProfileWidget_ru.properties
index 56c00af..fa6afbc 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties
+++ b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/widgets/UserProfileWidget_ru.properties
@@ -14,4 +14,8 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-auxClasses.palette=Auxiliary classes
+welcome=\u3088\u3046\u3053\u305d,
+
+name=Name
+lastLoginDate=Last Login Date
+lastChangePwdDate=Last Change Password Date
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/Captcha.html b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/Captcha.html
deleted file mode 100644
index 9593914..0000000
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/Captcha.html
+++ /dev/null
@@ -1,25 +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.
--->
-<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
- <wicket:panel>
- <div class="box-body">
- <span wicket:id="captchaPanel">[CAPTCHA]</span>
- </div>
- </wicket:panel>
-</html>
\ No newline at end of file
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/CaptchaPanel_pt_BR.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/CaptchaPanel_pt_BR.properties
deleted file mode 100644
index d21fb6b..0000000
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/CaptchaPanel_pt_BR.properties
+++ /dev/null
@@ -1,17 +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.
-captcha.message=Por favor, insira o c\u00f3digo exibido dentro da imagem.
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/CaptchaPanel_ru.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/CaptchaPanel_ru.properties
deleted file mode 100644
index 9a077bd..0000000
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/CaptchaPanel_ru.properties
+++ /dev/null
@@ -1,17 +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.
-captcha.message=\u041f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0432\u0432\u0435\u0434\u0438\u0442\u0435 \u043a\u043e\u0434, \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0439 \u043d\u0430 \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0435.
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.html b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.html
deleted file mode 100644
index f70fdfe..0000000
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.html
+++ /dev/null
@@ -1,35 +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.
--->
-<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
- <wicket:panel>
- <div class="col-xs-12">
- <div class="box">
- <div class="box-header">
- <h3 class="box-title">
- <wicket:message key="auxClasses.palette">AUX CLASSES</wicket:message>
- </h3>
- <span wicket:id="changed"></span>
- </div>
- <div class="box-body">
- <span wicket:id="auxClasses">[AUX CLASSES]</span>
- </div>
- </div>
- </div>
- </wicket:panel>
-</html>
\ No newline at end of file
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses_it.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses_it.properties
deleted file mode 100644
index 69fb846..0000000
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses_it.properties
+++ /dev/null
@@ -1,17 +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.
-auxClasses.palette=Classi ausiliarie
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses_ja.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses_ja.properties
deleted file mode 100644
index 5840b2f..0000000
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses_ja.properties
+++ /dev/null
@@ -1,17 +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.
-auxClasses.palette=\u88dc\u52a9\u30af\u30e9\u30b9
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/ui/commons/wizards/AjaxWizard.html b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/ui/commons/wizards/AjaxWizard.html
deleted file mode 100644
index 96f296e..0000000
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/ui/commons/wizards/AjaxWizard.html
+++ /dev/null
@@ -1,46 +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.
--->
-<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
- <head>
- <title></title>
- </head>
- <body>
- <wicket:panel>
- <div class="wizard-form">
- <form wicket:id="form">
- <div class="wizard-overview">
- <div wicket:id="overview"></div>
- </div>
- <div class="wizard-header">
- <div wicket:id="header"></div>
- </div>
- <div class="wizard-view">
- <div wicket:id="view"></div>
- </div>
- <div class="wizard-buttons">
- <div wicket:id="buttons"></div>
- </div>
- </form>
- </div>
- <span wicket:id="outerObjectsRepeater">
- <div wicket:id="outer"/>
- </span>
- </wicket:panel>
- </body>
-</html>
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/ui/commons/wizards/AjaxWizard.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/ui/commons/wizards/AjaxWizard.properties
deleted file mode 100644
index cafa9d6..0000000
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/ui/commons/wizards/AjaxWizard.properties
+++ /dev/null
@@ -1,23 +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.
-wizard.cancel.error = Wizard error on cancel
-wizard.apply.error = Wizard error on apply changes
-next=Next >
-previous=< Prev
-finish=Finish
-last=Last
-cancel=Cancel
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/ui/commons/wizards/AjaxWizardMgtButtonBar.html b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/ui/commons/wizards/AjaxWizardMgtButtonBar.html
deleted file mode 100644
index 4d21ce8..0000000
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/ui/commons/wizards/AjaxWizardMgtButtonBar.html
+++ /dev/null
@@ -1,38 +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.
--->
-<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
- <head>
- <title></title>
- </head>
- <body>
- <wicket:panel xmlns:wicket="http://wicket.apache.org">
-
- <span class="float-left">
- <input wicket:id="cancel" type="submit" wicket:message="value:cancel" class="btn btn-default"/>
- </span>
- <span class="float-right">
- <input wicket:id="previous" type="submit" wicket:message="value:previous" class="btn btn-default"/>
- <input wicket:id="next" type="submit" wicket:message="value:next" class="btn btn-default"/>
- <input wicket:id="last" type="submit" wicket:message="value:last" class="btn btn-default"/>
- <input wicket:id="finish" type="submit" wicket:message="value:finish" class="btn btn-success"/>
- </span>
-
- </wicket:panel>
- </body>
-</html>
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/ui/commons/wizards/AjaxWizard_it.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/ui/commons/wizards/AjaxWizard_it.properties
deleted file mode 100644
index 3230f79..0000000
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/ui/commons/wizards/AjaxWizard_it.properties
+++ /dev/null
@@ -1,23 +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.
-wizard.cancel.error = Errore wizard in annullamento operazione
-wizard.apply.error = Errore wizard in fase di commit
-next=Succ >
-previous=< Prec
-finish=Termina
-last=Ultimo
-cancel=Annulla
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/ui/commons/wizards/AjaxWizard_ja.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/ui/commons/wizards/AjaxWizard_ja.properties
deleted file mode 100644
index 8c1969a..0000000
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/ui/commons/wizards/AjaxWizard_ja.properties
+++ /dev/null
@@ -1,23 +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.
-wizard.cancel.error = \u30ad\u30e3\u30f3\u30bb\u30eb\u6642\u306b\u30a6\u30a3\u30b6\u30fc\u30c9\u30a8\u30e9\u30fc
-wizard.apply.error = \u5909\u66f4\u306e\u9069\u7528\u6642\u306b\u30a6\u30a3\u30b6\u30fc\u30c9\u30a8\u30e9\u30fc
-next=\u6b21\u3078 >
-previous=< \u524d\u3078
-finish=\u5b8c\u4e86
-last=\u6700\u5f8c
-cancel=\u30ad\u30e3\u30f3\u30bb\u30eb
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/ui/commons/wizards/AjaxWizard_pt_BR.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/ui/commons/wizards/AjaxWizard_pt_BR.properties
deleted file mode 100644
index 6cca386..0000000
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/ui/commons/wizards/AjaxWizard_pt_BR.properties
+++ /dev/null
@@ -1,23 +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.
-wizard.cancel.error = Erro em assistente de cancelar
-wizard.apply.error = Assistente de erro em aplicar as altera\u00e7\u00f5es
-next=Segu >
-previous=< Prec
-finish=Terminar
-last=\u00daltimo
-cancel=Cancelar
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/ui/commons/wizards/AjaxWizard_ru.properties b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/ui/commons/wizards/AjaxWizard_ru.properties
deleted file mode 100644
index af93f5a..0000000
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/ui/commons/wizards/AjaxWizard_ru.properties
+++ /dev/null
@@ -1,30 +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.
-# wizard.cancel.error = Во время отмены произошла ошибка
-wizard.cancel.error = \u0412\u043e \u0432\u0440\u0435\u043c\u044f \u043e\u0442\u043c\u0435\u043d\u044b \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0430
-# wizard.apply.error = Во время применения изменений произошла ошибка
-wizard.apply.error = \u0412\u043e \u0432\u0440\u0435\u043c\u044f \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0430
-# next=Далее >
-next=\u0414\u0430\u043b\u0435\u0435 >
-# previous=< Назад
-previous=< \u041d\u0430\u0437\u0430\u0434
-# finish=Завершить
-finish=\u0417\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044c
-# last=В конец
-last=\u0412 \u043a\u043e\u043d\u0435\u0446
-# cancel=Отмена
-cancel=\u041e\u0442\u043c\u0435\u043d\u0430
diff --git a/client/idrepo/enduser/src/test/java/org/apache/syncope/client/enduser/AbstractTest.java b/client/idrepo/enduser/src/test/java/org/apache/syncope/client/enduser/AbstractTest.java
new file mode 100644
index 0000000..c61be4e
--- /dev/null
+++ b/client/idrepo/enduser/src/test/java/org/apache/syncope/client/enduser/AbstractTest.java
@@ -0,0 +1,229 @@
+/*
+ * 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.enduser;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import com.giffing.wicket.spring.boot.context.extensions.WicketApplicationInitConfiguration;
+import com.giffing.wicket.spring.boot.context.extensions.boot.actuator.WicketEndpointRepository;
+import com.giffing.wicket.spring.boot.starter.app.classscanner.candidates.WicketClassCandidatesHolder;
+import com.giffing.wicket.spring.boot.starter.configuration.extensions.core.settings.general.GeneralSettingsProperties;
+import com.giffing.wicket.spring.boot.starter.configuration.extensions.external.spring.boot.actuator.WicketEndpointRepositoryDefault;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Properties;
+import java.util.stream.Stream;
+import org.apache.commons.lang3.tuple.Triple;
+import org.apache.cxf.jaxrs.client.Client;
+import org.apache.syncope.client.enduser.init.ClassPathScanImplementationLookup;
+import org.apache.syncope.client.lib.AuthenticationHandler;
+import org.apache.syncope.client.lib.SyncopeClient;
+import org.apache.syncope.client.lib.SyncopeClientFactoryBean;
+import org.apache.syncope.client.ui.commons.MIMETypesLoader;
+import org.apache.syncope.common.keymaster.client.api.DomainOps;
+import org.apache.syncope.common.keymaster.client.api.ServiceOps;
+import org.apache.syncope.common.keymaster.client.api.model.Domain;
+import org.apache.syncope.common.lib.info.NumbersInfo;
+import org.apache.syncope.common.lib.info.PlatformInfo;
+import org.apache.syncope.common.lib.info.SystemInfo;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.lib.to.AnyTypeTO;
+import org.apache.syncope.common.lib.to.PlainSchemaTO;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.AttrSchemaType;
+import org.apache.syncope.common.rest.api.beans.SchemaQuery;
+import org.apache.syncope.common.rest.api.service.AnyTypeService;
+import org.apache.syncope.common.rest.api.service.SchemaService;
+import org.apache.syncope.common.rest.api.service.SyncopeService;
+import org.apache.wicket.util.tester.WicketTester;
+import org.junit.jupiter.api.BeforeAll;
+import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+public abstract class AbstractTest {
+
+ @ImportAutoConfiguration
+ @Configuration
+ public static class SyncopeEnduserWebApplicationTestConfig {
+
+ @Bean
+ public ServiceOps selfServiceOps() {
+ return mock(ServiceOps.class);
+ }
+
+ @Bean
+ public DomainOps domainOps() {
+ DomainOps domainOps = mock(DomainOps.class);
+ when(domainOps.list()).thenReturn(List.of(new Domain.Builder(SyncopeConstants.MASTER_DOMAIN).build()));
+ return domainOps;
+ }
+
+ @Bean
+ public GeneralSettingsProperties generalSettingsProperties() {
+ return new GeneralSettingsProperties();
+ }
+
+ @Bean
+ public List<WicketApplicationInitConfiguration> configurations() {
+ return List.of();
+ }
+
+ @Bean
+ public WicketClassCandidatesHolder wicketClassCandidatesHolder() {
+ return new WicketClassCandidatesHolder();
+ }
+
+ @Bean
+ public WicketEndpointRepository wicketEndpointRepository() {
+ return new WicketEndpointRepositoryDefault();
+ }
+
+ @Bean
+ public ClassPathScanImplementationLookup classPathScanImplementationLookup() {
+ ClassPathScanImplementationLookup lookup = new ClassPathScanImplementationLookup();
+ lookup.load();
+ return lookup;
+ }
+
+ @Bean
+ public MIMETypesLoader mimeTypesLoader() {
+ MIMETypesLoader mimeTypesLoader = new MIMETypesLoader();
+ mimeTypesLoader.load();
+ return mimeTypesLoader;
+ }
+ }
+
+ public static class TestSyncopeWebApplication extends SyncopeWebApplication {
+
+ public interface SyncopeServiceClient extends SyncopeService, Client {
+ }
+
+ public interface AnyTypeServiceClient extends AnyTypeService, Client {
+ }
+
+ public interface SchemaServiceClient extends SchemaService, Client {
+ }
+
+ private SyncopeService getSyncopeService() {
+ SyncopeServiceClient service = mock(SyncopeServiceClient.class);
+ when(service.type(anyString())).thenReturn(service);
+ when(service.accept(anyString())).thenReturn(service);
+
+ when(service.platform()).thenReturn(new PlatformInfo());
+ when(service.system()).thenReturn(new SystemInfo());
+
+ NumbersInfo numbersInfo = new NumbersInfo();
+ Stream.of(NumbersInfo.ConfItem.values()).
+ forEach(item -> numbersInfo.getConfCompleteness().put(item.name(), true));
+ when(service.numbers()).thenReturn(numbersInfo);
+
+ return service;
+ }
+
+ private SchemaService getSchemaService() {
+ SchemaServiceClient service = mock(SchemaServiceClient.class);
+
+ when(service.type(anyString())).thenReturn(service);
+ when(service.accept(anyString())).thenReturn(service);
+
+ PlainSchemaTO firstname = new PlainSchemaTO();
+ firstname.setKey("firstname");
+ firstname.setType(AttrSchemaType.String);
+ firstname.setAnyTypeClass("minimal user");
+ firstname.setMandatoryCondition("false");
+ when(service.search(any(SchemaQuery.class))).thenReturn(List.of(firstname));
+ return service;
+ }
+
+ private AnyTypeService getAnyTypeService() {
+ AnyTypeServiceClient service = mock(AnyTypeServiceClient.class);
+
+ when(service.type(anyString())).thenReturn(service);
+ when(service.accept(anyString())).thenReturn(service);
+
+ AnyTypeTO anyTypeTO = new AnyTypeTO();
+ anyTypeTO.setKey("123456");
+ anyTypeTO.setKind(AnyTypeKind.USER);
+
+ when(service.read(anyString())).thenReturn(anyTypeTO);
+ return service;
+ }
+
+ private UserTO getUserTO() {
+ UserTO userTO = new UserTO();
+ userTO.setUsername("username");
+ return userTO;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public SyncopeClientFactoryBean newClientFactory() {
+ SyncopeClient client = mock(SyncopeClient.class);
+ when(client.getJWT()).thenReturn("<anyJWT>");
+
+ when(client.self()).thenReturn(Triple.of(new HashMap<>(), List.of(), getUserTO()));
+
+ SyncopeService syncopeService = getSyncopeService();
+ when(client.getService(SyncopeService.class)).thenReturn(syncopeService);
+
+ SchemaService schemaService = getSchemaService();
+ when(client.getService(SchemaService.class)).thenReturn(schemaService);
+
+ AnyTypeService anyTypeService = getAnyTypeService();
+ when(client.getService(AnyTypeService.class)).thenReturn(anyTypeService);
+
+ SyncopeClientFactoryBean clientFactory = mock(SyncopeClientFactoryBean.class);
+ when(clientFactory.setDomain(any())).thenReturn(clientFactory);
+ when(clientFactory.create(any(AuthenticationHandler.class))).thenReturn(client);
+ when(clientFactory.create(anyString(), anyString())).thenReturn(client);
+
+ return clientFactory;
+ }
+ }
+
+ protected static Properties PROPS;
+
+ protected static WicketTester TESTER;
+
+ @BeforeAll
+ public static void loadProps() throws IOException {
+ PROPS = new Properties();
+ try (InputStream is = AbstractTest.class.getResourceAsStream("/enduser.properties")) {
+ PROPS.load(is);
+ }
+ }
+
+ @BeforeAll
+ public static void setupTester() throws IOException {
+ AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
+ ctx.register(SyncopeEnduserWebApplicationTestConfig.class);
+ ctx.register(TestSyncopeWebApplication.class);
+ ctx.refresh();
+
+ TESTER = new WicketTester(ctx.getBean(SyncopeWebApplication.class));
+ }
+}
diff --git a/client/idrepo/enduser/src/test/java/org/apache/syncope/client/enduser/SyncopeEnduserApplicationTest.java b/client/idrepo/enduser/src/test/java/org/apache/syncope/client/enduser/SyncopeEnduserApplicationTest.java
new file mode 100644
index 0000000..1323395
--- /dev/null
+++ b/client/idrepo/enduser/src/test/java/org/apache/syncope/client/enduser/SyncopeEnduserApplicationTest.java
@@ -0,0 +1,138 @@
+/*
+ * 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.enduser;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.io.IOException;
+import java.security.AccessControlException;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ExecutionException;
+import javax.ws.rs.BadRequestException;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.enduser.pages.Dashboard;
+import org.apache.syncope.client.enduser.pages.Login;
+import org.apache.syncope.common.lib.SyncopeClientCompositeException;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.types.ClientExceptionType;
+import org.apache.wicket.feedback.FeedbackMessage;
+import org.apache.wicket.util.tester.FormTester;
+import org.junit.jupiter.api.Test;
+
+public class SyncopeEnduserApplicationTest extends AbstractTest {
+
+ private Map<String, String> getConfiguredSecurityHeaders() throws IOException {
+ Map<String, String> securityHeaders = new HashMap<>();
+
+ @SuppressWarnings("unchecked")
+ Enumeration<String> propNames = (Enumeration<String>) PROPS.propertyNames();
+ while (propNames.hasMoreElements()) {
+ String name = propNames.nextElement();
+ if (name.startsWith("security.headers.")) {
+ securityHeaders.put(StringUtils.substringAfter(name, "security.headers."), PROPS.getProperty(name));
+ }
+ }
+
+ return securityHeaders;
+ }
+
+ @Test
+ public void securityHeaders() throws IOException {
+ Map<String, String> securityHeaders = getConfiguredSecurityHeaders();
+ assertEquals(4, securityHeaders.size());
+
+ // 1. anonymous
+ TESTER.startPage(Login.class);
+ TESTER.assertRenderedPage(Login.class);
+ securityHeaders.forEach((key, value) -> assertEquals(value, TESTER.getLastResponse().getHeader(key)));
+
+ // 2. authenticated
+ FormTester formTester = TESTER.newFormTester("login");
+ formTester.setValue("username", "username");
+ formTester.setValue("password", "password");
+ formTester.submit("submit");
+
+ TESTER.assertRenderedPage(Dashboard.class);
+ securityHeaders.forEach((key, value) -> assertEquals(value, TESTER.getLastResponse().getHeader(key)));
+ }
+
+ @Test
+ public void errors() {
+ SyncopeEnduserSession session = SyncopeEnduserSession.get();
+
+ assertNull(session.getFeedbackMessages().first());
+
+ session.onException(new AccessControlException("JWT Expired"));
+ FeedbackMessage message = session.getFeedbackMessages().first();
+ assertNotNull(message);
+ assertTrue(message.isError());
+ assertEquals(SyncopeEnduserSession.Error.SESSION_EXPIRED.fallback(), message.getMessage());
+ session.getFeedbackMessages().clear();
+
+ session.onException(new AccessControlException("Auth Exception"));
+ message = session.getFeedbackMessages().first();
+ assertNotNull(message);
+ assertTrue(message.isError());
+ assertEquals(SyncopeEnduserSession.Error.AUTHORIZATION.fallback(), message.getMessage());
+ session.getFeedbackMessages().clear();
+
+ session.onException(new BadRequestException());
+ message = session.getFeedbackMessages().first();
+ assertNotNull(message);
+ assertTrue(message.isError());
+ assertEquals(SyncopeEnduserSession.Error.REST.fallback(), message.getMessage());
+ session.getFeedbackMessages().clear();
+
+ SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidUser);
+ sce.getElements().add("Error 1");
+ session.onException(sce);
+ message = session.getFeedbackMessages().first();
+ assertNotNull(message);
+ assertTrue(message.isError());
+ assertEquals(ClientExceptionType.InvalidUser.name() + ": Error 1", message.getMessage());
+ session.getFeedbackMessages().clear();
+
+ sce = SyncopeClientException.build(ClientExceptionType.InvalidUser);
+ sce.getElements().add("Error 1");
+ sce.getElements().add("Error 2");
+ session.onException(sce);
+ message = session.getFeedbackMessages().first();
+ assertNotNull(message);
+ assertTrue(message.isError());
+ assertEquals(ClientExceptionType.InvalidUser.name() + ": Error 1, Error 2", message.getMessage());
+ session.getFeedbackMessages().clear();
+
+ SyncopeClientCompositeException scce = SyncopeClientException.buildComposite();
+ scce.addException(SyncopeClientException.build(ClientExceptionType.InvalidUser));
+ scce.addException(SyncopeClientException.build(ClientExceptionType.InvalidExternalResource));
+ session.onException(new ExecutionException(scce));
+ message = session.getFeedbackMessages().first();
+ assertNotNull(message);
+ assertTrue(message.isError());
+ assertTrue(StringUtils.contains((CharSequence) message.getMessage(),
+ ClientExceptionType.InvalidExternalResource.name()));
+ assertTrue(StringUtils.contains((CharSequence) message.getMessage(), ClientExceptionType.InvalidUser.name()));
+ session.getFeedbackMessages().clear();
+ }
+}
diff --git a/client/idrepo/enduser/src/test/resources/log4j2.xml b/client/idrepo/enduser/src/test/resources/log4j2.xml
new file mode 100644
index 0000000..1da7c54
--- /dev/null
+++ b/client/idrepo/enduser/src/test/resources/log4j2.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<configuration status="WARN">
+
+ <appenders>
+
+ <Console name="main" target="SYSTEM_OUT">
+ <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %logger - %msg%n"/>
+ </Console>
+
+ </appenders>
+
+ <loggers>
+
+ <asyncLogger name="org.apache.syncope.client.lib" additivity="false" level="OFF">
+ <appender-ref ref="main"/>
+ </asyncLogger>
+
+ <asyncLogger name="org.apache.syncope.client.enduser" additivity="false" level="ERROR">
+ <appender-ref ref="main"/>
+ </asyncLogger>
+
+ <asyncLogger name="org.apache.wicket" additivity="false" level="ERROR">
+ <appender-ref ref="main"/>
+ </asyncLogger>
+
+ <asyncLogger name="org.apache.cxf" additivity="false" level="ERROR">
+ <appender-ref ref="main"/>
+ </asyncLogger>
+
+ <root level="ERROR">
+ <appender-ref ref="main"/>
+ </root>
+
+ </loggers>
+
+</configuration>
diff --git a/ext/flowable/client-enduser/src/main/java/org/apache/syncope/client/enduser/pages/Flowable.java b/ext/flowable/client-enduser/src/main/java/org/apache/syncope/client/enduser/pages/Flowable.java
index f7c3594..bffc121 100644
--- a/ext/flowable/client-enduser/src/main/java/org/apache/syncope/client/enduser/pages/Flowable.java
+++ b/ext/flowable/client-enduser/src/main/java/org/apache/syncope/client/enduser/pages/Flowable.java
@@ -24,29 +24,22 @@
import org.apache.commons.lang3.StringUtils;
import org.apache.syncope.client.enduser.SyncopeEnduserSession;
import org.apache.syncope.client.enduser.markup.html.form.BpmnProcessesAjaxPanel;
+import org.apache.syncope.client.enduser.panels.UserRequestDetails;
import org.apache.syncope.client.enduser.rest.BpmnProcessRestClient;
import org.apache.syncope.client.enduser.rest.UserRequestRestClient;
import org.apache.syncope.client.ui.commons.Constants;
import org.apache.syncope.client.ui.commons.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
import org.apache.syncope.client.ui.commons.annotations.ExtPage;
import org.apache.syncope.client.ui.commons.wicket.markup.html.bootstrap.tabs.Accordion;
-import org.apache.syncope.common.lib.SyncopeClientException;
import org.apache.syncope.common.lib.to.BpmnProcess;
import org.apache.syncope.common.lib.to.UserRequest;
-import org.apache.syncope.common.lib.to.UserRequestForm;
-import org.apache.syncope.ext.client.common.ui.panels.UserRequestFormPanel;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.AjaxLink;
-import org.apache.wicket.ajax.markup.html.form.AjaxButton;
import org.apache.wicket.ajax.markup.html.navigation.paging.AjaxPagingNavigator;
import org.apache.wicket.extensions.markup.html.repeater.util.SortParam;
import org.apache.wicket.extensions.markup.html.tabs.AbstractTab;
import org.apache.wicket.extensions.markup.html.tabs.ITab;
import org.apache.wicket.markup.html.WebMarkupContainer;
-import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.markup.html.form.Form;
-import org.apache.wicket.markup.html.panel.Fragment;
-import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.markup.repeater.Item;
import org.apache.wicket.markup.repeater.data.DataView;
import org.apache.wicket.markup.repeater.data.IDataProvider;
@@ -55,12 +48,14 @@
import org.apache.wicket.model.StringResourceModel;
import org.apache.wicket.request.mapper.parameter.PageParameters;
-@ExtPage(label = "User Requests", icon = "", listEntitlement = "")
-public class Flowable extends BaseExtPage {
+@ExtPage(label = "User Requests", icon = "fa fa-briefcase", listEntitlement = "")
+public class Flowable extends BasePage {
private static final long serialVersionUID = -8781434495150074529L;
- private final int rowsPerPage = 10;
+ private static final String USER_REQUESTS = "page.userRequests";
+
+ private final int rowsPerPage = 5;
private final Model<String> bpmnProcessModel = new Model<>();
@@ -69,7 +64,7 @@
private final DataView<UserRequest> urDataView;
public Flowable(final PageParameters parameters) {
- super(parameters);
+ super(parameters, USER_REQUESTS);
container = new WebMarkupContainer("content");
container.setOutputMarkupId(true);
@@ -83,15 +78,15 @@
protected void populateItem(final Item<UserRequest> item) {
final UserRequest userRequest = item.getModelObject();
item.add(new Accordion("userRequestDetails", Collections.<ITab>singletonList(new AbstractTab(
- new StringResourceModel("user.requests.accordion", container,
- Model.of(userRequest))) {
+ new StringResourceModel("user.requests.accordion", container, Model.of(userRequest))) {
private static final long serialVersionUID = 1037272333056449378L;
@Override
public WebMarkupContainer getPanel(final String panelId) {
// find the form associated to the current request, if any
- return new UserRequestDetails(panelId, userRequest);
+ return new UserRequestDetails(
+ panelId, userRequest, container, notificationPanel, getPageReference());
}
}), Model.of(-1)).setOutputMarkupId(true));
}
@@ -102,8 +97,7 @@
container.add(urDataView);
container.add(new AjaxPagingNavigator("navigator", urDataView));
- final AjaxLink<Void> startButton =
- new AjaxLink<>("start") {
+ AjaxLink<Void> startButton = new AjaxLink<Void>("start") {
private static final long serialVersionUID = 3669569969172391336L;
@@ -111,7 +105,7 @@
public void onClick(final AjaxRequestTarget target) {
if (StringUtils.isNotBlank(bpmnProcessModel.getObject())) {
try {
- UserRequestRestClient.start(bpmnProcessModel.getObject(), null);
+ UserRequestRestClient.startRequest(bpmnProcessModel.getObject(), null);
} catch (Exception e) {
LOG.error("Unable to start bpmnProcess [{}]", bpmnProcessModel.getObject(), e);
SyncopeEnduserSession.get()
@@ -127,98 +121,27 @@
container.add(startButton);
// autocomplete select with bpmnProcesses
- final BpmnProcessesAjaxPanel bpmnProcesses =
- new BpmnProcessesAjaxPanel("bpmnProcesses", "bpmnProcesses", bpmnProcessModel,
- new IndicatorAjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
+ BpmnProcessesAjaxPanel bpmnProcesses = new BpmnProcessesAjaxPanel("bpmnProcesses", "bpmnProcesses",
+ bpmnProcessModel, new IndicatorAjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
- private static final long serialVersionUID = -1107858522700306810L;
+ private static final long serialVersionUID = -1107858522700306810L;
- @Override
- protected void onUpdate(final AjaxRequestTarget target) {
- if (StringUtils.isNotBlank(bpmnProcessModel.getObject())) {
- startButton.setEnabled(true);
- } else {
- startButton.setEnabled(false);
- }
- target.add(container);
- }
- });
+ @Override
+ protected void onUpdate(final AjaxRequestTarget target) {
+ if (StringUtils.isNotBlank(bpmnProcessModel.getObject())) {
+ startButton.setEnabled(true);
+ } else {
+ startButton.setEnabled(false);
+ }
+ target.add(container);
+ }
+ });
bpmnProcesses.setChoices(BpmnProcessRestClient.getDefinitions().stream()
.filter(definition -> !definition.isUserWorkflow())
.map(BpmnProcess::getKey).collect(Collectors.toList()));
container.add(bpmnProcesses);
- body.add(container);
- }
-
- @Override
- protected void onBeforeRender() {
- super.onBeforeRender();
- navbar.setActiveNavItem(getClass().getSimpleName().toLowerCase());
- }
-
- public class UserRequestDetails extends Panel {
-
- private static final long serialVersionUID = -2447602429647965090L;
-
- public UserRequestDetails(final String id, final UserRequest userRequest) {
- super(id);
-
- final UserRequestForm formTO = userRequest.getHasForm()
- ? UserRequestRestClient.getForm(SyncopeEnduserSession.get().getSelfTO().getUsername(), userRequest.
- getTaskId()).orElse(null)
- : null;
-
- add(formTO == null || formTO.getProperties() == null || formTO.getProperties().isEmpty()
- ? new Fragment("fragContainer", "formDetails", UserRequestDetails.this)
- .add(new Label("executionId", userRequest.getExecutionId()))
- .add(new Label("startTime", userRequest.getStartTime()))
- : new Fragment("fragContainer", "formProperties", UserRequestDetails.this)
- .add(new Form<>("userRequestWrapForm").add(new UserRequestFormPanel(
- "userRequestFormPanel",
- formTO,
- false) {
-
- private static final long serialVersionUID = 3617895525072546591L;
-
- @Override
- protected void viewDetails(final AjaxRequestTarget target) {
- // do nothing
- }
- }).add(new AjaxButton("submit") {
-
- private static final long serialVersionUID = 4284361595033427185L;
-
- @Override
- protected void onSubmit(final AjaxRequestTarget target) {
- try {
- UserRequestRestClient.claimForm(formTO.getTaskId());
- UserRequestRestClient.submitForm(formTO);
- target.add(container);
- } catch (SyncopeClientException sce) {
- LOG.error("Unable to submit user request form for BPMN process [{}]",
- formTO.getBpmnProcess(), sce);
- SyncopeEnduserSession.get().error(StringUtils.isBlank(sce.getMessage())
- ? sce.getClass().getName()
- : sce.getMessage());
- notificationPanel.refresh(target);
- }
- }
-
- }.setOutputMarkupId(true))));
-
- add(new AjaxLink<Void>("delete") {
-
- private static final long serialVersionUID = 3669569969172391336L;
-
- @Override
- public void onClick(final AjaxRequestTarget target) {
- UserRequestRestClient.cancelRequest(userRequest.getExecutionId(), null);
- target.add(container);
- }
-
- });
- }
+ contentWrapper.add(container);
}
public static class URDataProvider implements IDataProvider<UserRequest> {
@@ -236,7 +159,7 @@
@Override
public Iterator<UserRequest> iterator(final long first, final long count) {
- final int page = ((int) first / paginatorRows);
+ int page = ((int) first / paginatorRows);
return UserRequestRestClient.listRequests((page < 0 ? 0 : page) + 1,
paginatorRows,
SyncopeEnduserSession.get().getSelfTO().getUsername(),
diff --git a/ext/flowable/client-enduser/src/main/java/org/apache/syncope/client/enduser/panels/UserRequestDetails.java b/ext/flowable/client-enduser/src/main/java/org/apache/syncope/client/enduser/panels/UserRequestDetails.java
new file mode 100644
index 0000000..cc3bf6b
--- /dev/null
+++ b/ext/flowable/client-enduser/src/main/java/org/apache/syncope/client/enduser/panels/UserRequestDetails.java
@@ -0,0 +1,126 @@
+/*
+ * 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.enduser.panels;
+
+import org.apache.syncope.client.enduser.SyncopeEnduserSession;
+import org.apache.syncope.client.enduser.rest.UserRequestRestClient;
+import org.apache.syncope.client.ui.commons.panels.NotificationPanel;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.ProvisioningResult;
+import org.apache.syncope.common.lib.to.UserRequest;
+import org.apache.syncope.common.lib.to.UserRequestForm;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.common.lib.types.ExecStatus;
+import org.apache.syncope.ext.client.common.ui.panels.UserRequestFormPanel;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.markup.html.AjaxLink;
+import org.apache.wicket.ajax.markup.html.form.AjaxButton;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.markup.html.panel.Fragment;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class UserRequestDetails extends Panel {
+
+ private static final long serialVersionUID = -2447602429647965090L;
+
+ protected static final Logger LOG = LoggerFactory.getLogger(UserRequestDetails.class);
+
+ private static final String USER_REQUEST_ERROR = "user_request_error";
+
+ public UserRequestDetails(
+ final String id,
+ final UserRequest userRequest,
+ final WebMarkupContainer container,
+ final NotificationPanel notificationPanel,
+ final PageReference pageRef) {
+
+ super(id);
+
+ UserRequestForm formTO = userRequest.getHasForm()
+ ? UserRequestRestClient.getForm(
+ SyncopeEnduserSession.get().getSelfTO().getUsername(),
+ userRequest.getTaskId()).orElse(null)
+ : null;
+
+ if (formTO == null || formTO.getProperties() == null || formTO.getProperties().isEmpty()) {
+ add(new Fragment("fragContainer", "formDetails", UserRequestDetails.this)
+ .add(new Label("executionId", userRequest.getExecutionId()))
+ .add(new Label("startTime", userRequest.getStartTime())));
+ } else {
+ Form<Void> form = new Form<>("userRequestWrapForm");
+
+ form.add(new UserRequestFormPanel("userRequestFormPanel", pageRef, formTO, false) {
+
+ private static final long serialVersionUID = 3617895525072546591L;
+
+ @Override
+ protected void viewDetails(final AjaxRequestTarget target) {
+ // do nothing
+ }
+ });
+
+ form.add(new AjaxButton("submit") {
+
+ private static final long serialVersionUID = 4284361595033427185L;
+
+ @Override
+ protected void onSubmit(final AjaxRequestTarget target) {
+ try {
+ UserRequestRestClient.claimForm(formTO.getTaskId());
+ ProvisioningResult<UserTO> result = UserRequestRestClient.submitForm(formTO);
+
+ if (result.getPropagationStatuses().stream().
+ anyMatch(p -> ExecStatus.FAILURE == p.getStatus()
+ || ExecStatus.NOT_ATTEMPTED == p.getStatus())) {
+
+ SyncopeEnduserSession.get().error(getString(USER_REQUEST_ERROR));
+ notificationPanel.refresh(target);
+ }
+
+ target.add(container);
+ } catch (SyncopeClientException sce) {
+ LOG.error("Unable to submit user request form for BPMN process [{}]",
+ formTO.getBpmnProcess(), sce);
+ SyncopeEnduserSession.get().error(getString(USER_REQUEST_ERROR));
+ notificationPanel.refresh(target);
+ }
+ }
+
+ }.setOutputMarkupId(true));
+
+ add(new Fragment("fragContainer", "formProperties", UserRequestDetails.this).add(form));
+ }
+
+ add(new AjaxLink<Void>("delete") {
+
+ private static final long serialVersionUID = 3669569969172391336L;
+
+ @Override
+ public void onClick(final AjaxRequestTarget target) {
+ UserRequestRestClient.cancelRequest(userRequest.getExecutionId(), null);
+ target.add(container);
+ }
+ });
+ }
+}
diff --git a/ext/flowable/client-enduser/src/main/java/org/apache/syncope/client/enduser/rest/BaseRestClient.java b/ext/flowable/client-enduser/src/main/java/org/apache/syncope/client/enduser/rest/BaseRestClient.java
new file mode 100644
index 0000000..278d04b
--- /dev/null
+++ b/ext/flowable/client-enduser/src/main/java/org/apache/syncope/client/enduser/rest/BaseRestClient.java
@@ -0,0 +1,68 @@
+/*
+ * 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.enduser.rest;
+
+import org.apache.syncope.client.enduser.SyncopeEnduserSession;
+import org.apache.syncope.client.lib.SyncopeClient;
+import org.apache.syncope.common.lib.search.OrderByClauseBuilder;
+import org.apache.syncope.common.rest.api.service.SyncopeService;
+import org.apache.wicket.extensions.markup.html.repeater.util.SortParam;
+import org.apache.syncope.client.ui.commons.rest.RestClient;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public abstract class BaseRestClient implements RestClient {
+
+ protected static final Logger LOG = LoggerFactory.getLogger(BaseRestClient.class);
+
+ private static final long serialVersionUID = 1523999867826481989L;
+
+ public static SyncopeService getSyncopeService() {
+ return getService(SyncopeService.class);
+ }
+
+ protected static <T> T getService(final Class<T> serviceClass) {
+ return SyncopeEnduserSession.get().getService(serviceClass);
+ }
+
+ protected static <T> T getService(final String etag, final Class<T> serviceClass) {
+ return SyncopeEnduserSession.get().getService(etag, serviceClass);
+ }
+
+ protected static <T> void resetClient(final Class<T> serviceClass) {
+ SyncopeEnduserSession.get().resetClient(serviceClass);
+ }
+
+ protected static String toOrderBy(final SortParam<String> sort) {
+ OrderByClauseBuilder builder = SyncopeClient.getOrderByClauseBuilder();
+
+ String property = sort.getProperty();
+ if (property.indexOf('#') != -1) {
+ property = property.substring(property.indexOf('#') + 1);
+ }
+
+ if (sort.isAscending()) {
+ builder.asc(property);
+ } else {
+ builder.desc(property);
+ }
+
+ return builder.build();
+ }
+}
diff --git a/ext/flowable/client-enduser/src/main/java/org/apache/syncope/client/enduser/rest/UserRequestRestClient.java b/ext/flowable/client-enduser/src/main/java/org/apache/syncope/client/enduser/rest/UserRequestRestClient.java
index 71d9cf6..93a5670 100644
--- a/ext/flowable/client-enduser/src/main/java/org/apache/syncope/client/enduser/rest/UserRequestRestClient.java
+++ b/ext/flowable/client-enduser/src/main/java/org/apache/syncope/client/enduser/rest/UserRequestRestClient.java
@@ -20,10 +20,13 @@
import java.util.List;
import java.util.Optional;
+import javax.ws.rs.core.GenericType;
import org.apache.commons.lang3.StringUtils;
import org.apache.syncope.client.enduser.SyncopeEnduserSession;
+import org.apache.syncope.common.lib.to.ProvisioningResult;
import org.apache.syncope.common.lib.to.UserRequest;
import org.apache.syncope.common.lib.to.UserRequestForm;
+import org.apache.syncope.common.lib.to.UserTO;
import org.apache.syncope.common.rest.api.beans.UserRequestQuery;
import org.apache.wicket.extensions.markup.html.repeater.util.SortParam;
import org.apache.syncope.common.rest.api.service.UserRequestService;
@@ -46,12 +49,11 @@
final int size,
final String username,
final SortParam<String> sort) {
-
return getService(UserRequestService.class).listRequests(new UserRequestQuery.Builder().
user(StringUtils.isBlank(username)
? SyncopeEnduserSession.get().getSelfTO().getUsername()
: username).
- page(page).size(size).orderBy(toOrderBy(sort)).build()).getResult();
+ page(page).size(size).build()).getResult();
}
public static void cancelRequest(final String executionId, final String reason) {
@@ -64,7 +66,7 @@
getTotalCount();
}
- public static List<UserRequestForm> getForms(final int page, final int size, final SortParam<String> sort) {
+ public static List<UserRequestForm> listForms(final int page, final int size, final SortParam<String> sort) {
return getService(UserRequestService.class).
listForms(new UserRequestQuery.Builder().page(page).size(size).orderBy(toOrderBy(sort)).build()).
getResult();
@@ -77,11 +79,13 @@
taskId));
}
- public static void submitForm(final UserRequestForm form) {
- getService(UserRequestService.class).submitForm(form);
+ public static ProvisioningResult<UserTO> submitForm(final UserRequestForm form) {
+ return getService(UserRequestService.class).submitForm(form).readEntity(
+ new GenericType<ProvisioningResult<UserTO>>() {
+ });
}
- public static void start(final String bpmnProcess, final String user) {
+ public static void startRequest(final String bpmnProcess, final String user) {
getService(UserRequestService.class).startRequest(bpmnProcess, user, null);
}
diff --git a/ext/flowable/client-enduser/src/main/java/org/apache/syncope/ext/client/common/ui/panels/UserRequestFormPanel.java b/ext/flowable/client-enduser/src/main/java/org/apache/syncope/ext/client/common/ui/panels/UserRequestFormPanel.java
new file mode 100644
index 0000000..f83c9a8
--- /dev/null
+++ b/ext/flowable/client-enduser/src/main/java/org/apache/syncope/ext/client/common/ui/panels/UserRequestFormPanel.java
@@ -0,0 +1,220 @@
+/*
+ * 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.ext.client.common.ui.panels;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.math.NumberUtils;
+import org.apache.commons.lang3.time.FastDateFormat;
+import org.apache.syncope.client.ui.commons.MapChoiceRenderer;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDateTimeFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxPasswordFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxSpinnerFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.FieldPanel;
+import org.apache.syncope.common.lib.to.UserRequestForm;
+import org.apache.syncope.common.lib.to.UserRequestFormProperty;
+import org.apache.syncope.common.lib.to.UserRequestFormPropertyValue;
+import org.apache.syncope.common.lib.types.IdRepoEntitlement;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.markup.html.AjaxLink;
+import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
+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.LoadableDetachableModel;
+import org.apache.wicket.model.PropertyModel;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public abstract class UserRequestFormPanel extends Panel {
+
+ private static final long serialVersionUID = -8847854414429745216L;
+
+ protected static final Logger LOG = LoggerFactory.getLogger(UserRequestFormPanel.class);
+
+ public UserRequestFormPanel(final String id, final PageReference pageRef, final UserRequestForm form) {
+ this(id, pageRef, form, true);
+ }
+
+ public UserRequestFormPanel(final String id, final PageReference pageRef, final UserRequestForm form,
+ final boolean showDetails) {
+ super(id);
+
+ IModel<List<UserRequestFormProperty>> formProps = new LoadableDetachableModel<List<UserRequestFormProperty>>() {
+
+ private static final long serialVersionUID = 3169142472626817508L;
+
+ @Override
+ protected List<UserRequestFormProperty> load() {
+ return form.getProperties();
+ }
+ };
+
+ ListView<UserRequestFormProperty> propView = new ListView<UserRequestFormProperty>("propView", formProps) {
+
+ private static final long serialVersionUID = 9101744072914090143L;
+
+ @Override
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ protected void populateItem(final ListItem<UserRequestFormProperty> item) {
+ final UserRequestFormProperty prop = item.getModelObject();
+
+ String label = StringUtils.isBlank(prop.getName()) ? prop.getId() : prop.getName();
+
+ FieldPanel field;
+ switch (prop.getType()) {
+ case Boolean:
+ field = new AjaxDropDownChoicePanel("value", label, new PropertyModel<String>(prop, "value") {
+
+ private static final long serialVersionUID = -3743432456095828573L;
+
+ @Override
+ public String getObject() {
+ return StringUtils.isBlank(prop.getValue())
+ ? null
+ : prop.getValue().equals("true") ? "Yes" : "No";
+ }
+
+ @Override
+ public void setObject(final String object) {
+ prop.setValue(String.valueOf(object.equalsIgnoreCase("yes")));
+ }
+
+ }, false).setChoices(Arrays.asList(new String[] { "Yes", "No" }));
+ break;
+
+ case Date:
+ FastDateFormat formatter = FastDateFormat.getInstance(prop.getDatePattern());
+ field = new AjaxDateTimeFieldPanel("value", label, new PropertyModel<Date>(prop, "value") {
+
+ private static final long serialVersionUID = -3743432456095828573L;
+
+ @Override
+ public Date getObject() {
+ try {
+ return StringUtils.isBlank(prop.getValue())
+ ? null
+ : formatter.parse(prop.getValue());
+ } catch (ParseException e) {
+ LOG.error("Unparsable date: {}", prop.getValue(), e);
+ return null;
+ }
+ }
+
+ @Override
+ public void setObject(final Date object) {
+ prop.setValue(formatter.format(object));
+ }
+
+ }, formatter);
+ break;
+
+ case Enum:
+ field = new AjaxDropDownChoicePanel(
+ "value", label, new PropertyModel<String>(prop, "value"), false).
+ setChoiceRenderer(new MapChoiceRenderer(prop.getEnumValues().stream().
+ collect(Collectors.toMap(
+ UserRequestFormPropertyValue::getKey,
+ UserRequestFormPropertyValue::getValue)))).
+ setChoices(new ArrayList<>(prop.getEnumValues().stream().
+ map(UserRequestFormPropertyValue::getKey).collect(Collectors.toList())));
+ break;
+
+ case Dropdown:
+ field = new AjaxDropDownChoicePanel(
+ "value", label, new PropertyModel<String>(prop, "value"), false).
+ setChoiceRenderer(new MapChoiceRenderer(prop.getDropdownValues().stream().
+ collect(Collectors.toMap(
+ UserRequestFormPropertyValue::getKey,
+ UserRequestFormPropertyValue::getValue)))).
+ setChoices(prop.getDropdownValues().stream().
+ map(UserRequestFormPropertyValue::getKey).collect(Collectors.toList()));
+ break;
+
+ case Long:
+ field = new AjaxSpinnerFieldPanel.Builder<Long>().build(
+ "value",
+ label,
+ Long.class,
+ new PropertyModel<Long>(prop, "value") {
+
+ private static final long serialVersionUID = -7688359318035249200L;
+
+ @Override
+ public Long getObject() {
+ return StringUtils.isBlank(prop.getValue())
+ ? null
+ : NumberUtils.toLong(prop.getValue());
+ }
+
+ @Override
+ public void setObject(final Long object) {
+ prop.setValue(String.valueOf(object));
+ }
+ });
+ break;
+
+ case Password:
+ field = new AjaxPasswordFieldPanel("value", label, new PropertyModel<>(prop, "value"), false);
+ break;
+
+ case String:
+ default:
+ field = new AjaxTextFieldPanel("value", label, new PropertyModel<>(prop, "value"), false);
+ break;
+ }
+
+ field.setReadOnly(!prop.isWritable());
+ if (prop.isRequired()) {
+ field.addRequiredLabel();
+ }
+
+ item.add(field);
+ }
+ };
+
+ AjaxLink<String> userDetails = new AjaxLink<String>("userDetails") {
+
+ private static final long serialVersionUID = -4804368561204623354L;
+
+ @Override
+ public void onClick(final AjaxRequestTarget target) {
+ viewDetails(target);
+ }
+ };
+ MetaDataRoleAuthorizationStrategy.authorize(userDetails, ENABLE, IdRepoEntitlement.USER_READ);
+
+ boolean enabled = form.getUserTO() != null;
+ userDetails.setVisible(enabled && showDetails).setEnabled(enabled);
+
+ add(propView);
+ add(userDetails);
+ }
+
+ protected abstract void viewDetails(AjaxRequestTarget target);
+}
diff --git a/ext/flowable/client-enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Flowable$UserRequestDetails.html b/ext/flowable/client-enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Flowable$UserRequestDetails.html
deleted file mode 100644
index 8988d6d..0000000
--- a/ext/flowable/client-enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Flowable$UserRequestDetails.html
+++ /dev/null
@@ -1,36 +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.
--->
-<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
- <wicket:panel>
- <span wicket:id="fragContainer"/>
- <wicket:fragment wicket:id="formProperties">
- <form wicket:id="userRequestWrapForm" class="form-horizontal">
- <span wicket:id="userRequestFormPanel"></span>
- <div>
- <input wicket:id="submit" type="submit" wicket:message="value:submit" class="btn btn-success pull-right"/>
- </div>
- </form>
- </wicket:fragment>
- <wicket:fragment wicket:id="formDetails">
- <span><wicket:message key="executionId"/>: <label wicket:id="executionId"/></span>
- <span><wicket:message key="startTime"/>: <label wicket:id="startTime"/></span>
- </wicket:fragment>
- <input wicket:id="delete" type="button" wicket:message="value:delete" class="btn btn-danger pull-left">
- </wicket:panel>
-</html>
diff --git a/ext/flowable/client-enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Flowable.html b/ext/flowable/client-enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Flowable.html
index b3cd215..2bd1aa3 100644
--- a/ext/flowable/client-enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Flowable.html
+++ b/ext/flowable/client-enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Flowable.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
@@ -19,40 +20,58 @@
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
<wicket:extend>
<section class="content" wicket:id="content">
- <div id="flowable_wrapper" class="container-fluid password_reset_wrapper">
- <div class="row">
- <div class="col-md-6 col-md-offset-3">
-
- <div class="page-header">
- <h1>
- <wicket:message key="bpmn.process.title">[BPMN_PROCESSES_TITLE]</wicket:message>
- </h1>
+ <div class="box">
+ <div class="row clearfix">
+ <div class="col-md-12">
+ <div class="col-md-6 col-md-offset-3">
+ <div>
+ <h3 class="box-title"></h3>
+ </div>
+ <div class="box-body">
+ <div class="box-header formcard">
+ <header class="card-container card-red">
+ <h4><wicket:message key="bpmn.process.title">[BPMN_PROCESSES_TITLE]</wicket:message></h4>
+ </header>
+ <div class="card-container-body">
+ <div>
+ <div class="col-xs-12">
+ <div class="form-group">
+ <span wicket:id="bpmnProcesses" class="bpmn-process-span">[BPMN PROCESSES]</span>
+ <input wicket:id="start" wicket:message="value:start" type="button" class="btn btn-success">
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div class="box-body">
+ <div class="box-header formcard">
+ <header class="card-container card-red">
+ <h4><wicket:message key="requests.to.be.approved">[ACTIVE REQUEST]</wicket:message></h4>
+ </header>
+ <div class="card-container-body">
+ <div>
+ <div class="col-xs-12">
+ <div class="form-group">
+ <div wicket:id="userRequests">
+ <div wicket:id="userRequestDetails"/>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div class="box-footer">
+ <table class="paginator">
+ <tfoot>
+ <tr>
+ <td wicket:id="navigator"></td>
+ </tr>
+ </tfoot>
+ </table>
+ </div>
</div>
-
- <div>
- <span wicket:id="bpmnProcesses">[BPMN PROCESSES]</span>
- <input wicket:id="start" wicket:message="value:start" type="button" class="btn btn-success">
- </div>
-
- </div>
- </div>
-
- <div class="row">
- <div class="col-md-6 col-md-offset-3">
- <table>
- <tbody>
- <tr wicket:id="userRequests">
- <td>
- <div wicket:id="userRequestDetails"/>
- </td>
- </tr>
- </tbody>
- <tfoot>
- <tr>
- <td wicket:id="navigator"></td>
- </tr>
- </tfoot>
- </table>
</div>
</div>
</div>
diff --git a/ext/flowable/client-enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Flowable.properties b/ext/flowable/client-enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Flowable.properties
index 1cb340b..61a1f70 100644
--- a/ext/flowable/client-enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Flowable.properties
+++ b/ext/flowable/client-enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Flowable.properties
@@ -21,3 +21,4 @@
startTime=Start time
delete=Delete
start=Start
+requests.to.be.approved=Your active requests
diff --git a/ext/flowable/client-enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Flowable_it.properties b/ext/flowable/client-enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Flowable_it.properties
index 896af9e..5f11651 100644
--- a/ext/flowable/client-enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Flowable_it.properties
+++ b/ext/flowable/client-enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Flowable_it.properties
@@ -21,3 +21,4 @@
startTime=Eseguito il
delete=Cancella
start=Esegui
+requests.to.be.approved=Richieste in lavorazione
diff --git a/ext/flowable/client-enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Flowable_ja.properties b/ext/flowable/client-enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Flowable_ja.properties
index f08cec1..64bcf41 100644
--- a/ext/flowable/client-enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Flowable_ja.properties
+++ b/ext/flowable/client-enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Flowable_ja.properties
@@ -21,3 +21,4 @@
startTime=\u59cb\u307e\u308b\u6642\u9593
delete=\u30af\u30ea\u30a2
start=\u958b\u59cb
+requests.to.be.approved=\u3042\u306a\u305f\u306e\u30a2\u30af\u30c6\u30a3\u30d6\u306a\u30ea\u30af\u30a8\u30b9\u30c8
diff --git a/ext/flowable/client-enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Flowable_pt_BR.properties b/ext/flowable/client-enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Flowable_pt_BR.properties
index 0fcaf09..947d75e 100644
--- a/ext/flowable/client-enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Flowable_pt_BR.properties
+++ b/ext/flowable/client-enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Flowable_pt_BR.properties
@@ -21,3 +21,4 @@
startTime=Hora de in\u00edcio
delete=Limpa
start=Come\u00e7ar
+requests.to.be.approved=Seus pedidos ativos
diff --git a/ext/flowable/client-enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Flowable_ru.properties b/ext/flowable/client-enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Flowable_ru.properties
index 9164ee7..5dba976 100644
--- a/ext/flowable/client-enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Flowable_ru.properties
+++ b/ext/flowable/client-enduser/src/main/resources/org/apache/syncope/client/enduser/pages/Flowable_ru.properties
@@ -21,3 +21,4 @@
startTime=\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0435 \u0432\u0440\u0435\u043c\u044f
delete=\u0440\u0430\u0441\u0441\u0435\u0435\u0442\u0441\u044f
start=\u041d\u0430\u0447\u043d\u0438\u0442\u0435
+requests.to.be.approved=\u0412\u0430\u0448\u0438 \u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b
diff --git a/ext/flowable/client-enduser/src/main/resources/org/apache/syncope/client/enduser/pages/UserRequestForms.html b/ext/flowable/client-enduser/src/main/resources/org/apache/syncope/client/enduser/pages/UserRequestForms.html
index a89d762..f5058ac 100644
--- a/ext/flowable/client-enduser/src/main/resources/org/apache/syncope/client/enduser/pages/UserRequestForms.html
+++ b/ext/flowable/client-enduser/src/main/resources/org/apache/syncope/client/enduser/pages/UserRequestForms.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
diff --git a/ext/flowable/client-enduser/src/main/resources/org/apache/syncope/client/enduser/panels/UserRequestDetails.html b/ext/flowable/client-enduser/src/main/resources/org/apache/syncope/client/enduser/panels/UserRequestDetails.html
new file mode 100644
index 0000000..84c189a
--- /dev/null
+++ b/ext/flowable/client-enduser/src/main/resources/org/apache/syncope/client/enduser/panels/UserRequestDetails.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<!--
+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.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
+ <wicket:panel>
+ <div class="card-container-padding">
+ <span wicket:id="fragContainer"/>
+ <wicket:fragment wicket:id="formProperties">
+ <form wicket:id="userRequestWrapForm" class="form-horizontal">
+ <span wicket:id="userRequestFormPanel"></span>
+ <div>
+ <input wicket:id="submit" type="submit" wicket:message="value:submit" class="btn btn-success pull-right"/>
+ </div>
+ </form>
+ </wicket:fragment>
+ <wicket:fragment wicket:id="formDetails">
+ <span><wicket:message key="executionId"/>: <label wicket:id="executionId"/></span>
+ <span><wicket:message key="startTime"/>: <label wicket:id="startTime"/></span>
+ </wicket:fragment>
+ <input wicket:id="delete" type="button" wicket:message="value:delete" class="btn btn-danger pull-left">
+ </div>
+ </wicket:panel>
+</html>
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/UserDetails$EditUserPasswordPanel.html b/ext/flowable/client-enduser/src/main/resources/org/apache/syncope/ext/client/common/ui/panels/UserRequestFormPanel.html
similarity index 73%
copy from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/UserDetails$EditUserPasswordPanel.html
copy to ext/flowable/client-enduser/src/main/resources/org/apache/syncope/ext/client/common/ui/panels/UserRequestFormPanel.html
index e77ed5d..7a9b26b 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/UserDetails$EditUserPasswordPanel.html
+++ b/ext/flowable/client-enduser/src/main/resources/org/apache/syncope/ext/client/common/ui/panels/UserRequestFormPanel.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
@@ -18,12 +19,14 @@
-->
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
<wicket:panel>
- <div id="editUserChangePassword">
- <div class="alert alert-warning">
- <i class="fas fa-exclamation-triangle"></i> <label wicket:id="warning">[warning]</label>
- </div>
+ <div wicket:id="propView">
+ <span wicket:id="value">[value]</span>
+ </div>
- <div wicket:id="passwordPanel">[change password panel]</div>
+ <div style="margin: 20px 0">
+ <a href="#" alt="user details" class="btn btn-success btn-circle btn-lg" wicket:id="userDetails" wicket:message="title:userDetails">
+ <i class="fas fa-eye"></i>
+ </a>
</div>
</wicket:panel>
</html>
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties b/ext/flowable/client-enduser/src/main/resources/org/apache/syncope/ext/client/common/ui/panels/UserRequestFormPanel.properties
similarity index 93%
copy from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties
copy to ext/flowable/client-enduser/src/main/resources/org/apache/syncope/ext/client/common/ui/panels/UserRequestFormPanel.properties
index 56c00af..450ff50 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties
+++ b/ext/flowable/client-enduser/src/main/resources/org/apache/syncope/ext/client/common/ui/panels/UserRequestFormPanel.properties
@@ -14,4 +14,5 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-auxClasses.palette=Auxiliary classes
+userDetails=User details
+userForm=Edit User
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties b/ext/flowable/client-enduser/src/main/resources/org/apache/syncope/ext/client/common/ui/panels/UserRequestFormPanel_it.properties
similarity index 92%
copy from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties
copy to ext/flowable/client-enduser/src/main/resources/org/apache/syncope/ext/client/common/ui/panels/UserRequestFormPanel_it.properties
index 56c00af..92c475d 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties
+++ b/ext/flowable/client-enduser/src/main/resources/org/apache/syncope/ext/client/common/ui/panels/UserRequestFormPanel_it.properties
@@ -14,4 +14,5 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-auxClasses.palette=Auxiliary classes
+userDetails=Dettagli utente
+userForm=Modifica utente
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties b/ext/flowable/client-enduser/src/main/resources/org/apache/syncope/ext/client/common/ui/panels/UserRequestFormPanel_ja.properties
similarity index 87%
copy from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties
copy to ext/flowable/client-enduser/src/main/resources/org/apache/syncope/ext/client/common/ui/panels/UserRequestFormPanel_ja.properties
index 56c00af..5a9cc2d 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses.properties
+++ b/ext/flowable/client-enduser/src/main/resources/org/apache/syncope/ext/client/common/ui/panels/UserRequestFormPanel_ja.properties
@@ -14,4 +14,5 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-auxClasses.palette=Auxiliary classes
+userDetails=\u30e6\u30fc\u30b6\u30fc\u8a73\u7d30
+userForm=\u30e6\u30fc\u30b6\u30fc\u3092\u7de8\u96c6
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses_pt_BR.properties b/ext/flowable/client-enduser/src/main/resources/org/apache/syncope/ext/client/common/ui/panels/UserRequestFormPanel_pt_BR.properties
similarity index 91%
rename from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses_pt_BR.properties
rename to ext/flowable/client-enduser/src/main/resources/org/apache/syncope/ext/client/common/ui/panels/UserRequestFormPanel_pt_BR.properties
index c91f75c..00a8971 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/wizards/any/EnduserAuxClasses_pt_BR.properties
+++ b/ext/flowable/client-enduser/src/main/resources/org/apache/syncope/ext/client/common/ui/panels/UserRequestFormPanel_pt_BR.properties
@@ -14,4 +14,5 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-auxClasses.palette=Classes auxiliares
+userDetails=Detalhes do Usu\u00e1rio
+userForm=Detalhes do Usu\u00e1rio
diff --git a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel_pt_BR.properties b/ext/flowable/client-enduser/src/main/resources/org/apache/syncope/ext/client/common/ui/panels/UserRequestFormPanel_ru.properties
similarity index 71%
copy from client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel_pt_BR.properties
copy to ext/flowable/client-enduser/src/main/resources/org/apache/syncope/ext/client/common/ui/panels/UserRequestFormPanel_ru.properties
index cf3ca73..89dd721 100644
--- a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SelfPwdResetPanel_pt_BR.properties
+++ b/ext/flowable/client-enduser/src/main/resources/org/apache/syncope/ext/client/common/ui/panels/UserRequestFormPanel_ru.properties
@@ -14,12 +14,5 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-username=Nome de usu\u00e1rio\n
-securityQuestion=Pergunta de Seguran\u00e7a
-securityAnswer=Resposta de seguran\u00e7a
-reload=recarregar
-not.loading=N\u00e3o est\u00e1 carregando?
-submit=Enviar
-cancel=Cancelar
-self.pwd.reset.success=Senha redefinida com sucesso
-domain=Domain
+userDetails=\u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435
+userForm=\u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435
diff --git a/ext/oidcc4ui/client-enduser/src/main/java/org/apache/syncope/client/enduser/panels/OIDCSSOLoginFormPanel.java b/ext/oidcc4ui/client-enduser/src/main/java/org/apache/syncope/client/enduser/panels/OIDCSSOLoginFormPanel.java
index ca89994..f521aff 100644
--- a/ext/oidcc4ui/client-enduser/src/main/java/org/apache/syncope/client/enduser/panels/OIDCSSOLoginFormPanel.java
+++ b/ext/oidcc4ui/client-enduser/src/main/java/org/apache/syncope/client/enduser/panels/OIDCSSOLoginFormPanel.java
@@ -18,12 +18,12 @@
*/
package org.apache.syncope.client.enduser.panels;
-import org.apache.syncope.client.ui.commons.panels.AbstractOIDCSSOLoginFormPanel;
import org.apache.syncope.client.ui.commons.BaseSession;
+import org.apache.syncope.client.ui.commons.panels.AbstractOIDCSSOLoginFormPanel;
public class OIDCSSOLoginFormPanel extends AbstractOIDCSSOLoginFormPanel {
- private static final long serialVersionUID = 4312771213433968542L;
+ private static final long serialVersionUID = 1154933731474854671L;
public OIDCSSOLoginFormPanel(final String id, final BaseSession session) {
super(id, session);
diff --git a/ext/oidcc4ui/client-enduser/src/main/java/org/apache/syncope/client/enduser/resources/EnduserCodeConsumerResource.java b/ext/oidcc4ui/client-enduser/src/main/java/org/apache/syncope/client/enduser/resources/EnduserCodeConsumerResource.java
index 2e7055c..f542b0b 100644
--- a/ext/oidcc4ui/client-enduser/src/main/java/org/apache/syncope/client/enduser/resources/EnduserCodeConsumerResource.java
+++ b/ext/oidcc4ui/client-enduser/src/main/java/org/apache/syncope/client/enduser/resources/EnduserCodeConsumerResource.java
@@ -21,7 +21,7 @@
import com.fasterxml.jackson.core.JsonProcessingException;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.syncope.client.enduser.pages.OIDCClientLogin;
-import org.apache.syncope.client.enduser.pages.Self;
+import org.apache.syncope.client.enduser.pages.SelfRegistration;
import org.apache.syncope.client.ui.commons.annotations.Resource;
import org.apache.syncope.client.ui.commons.panels.OIDCC4UIConstants;
import org.apache.syncope.client.ui.commons.resources.oidcc4ui.CodeConsumerResource;
@@ -44,7 +44,7 @@
@Override
protected Pair<Class<? extends WebPage>, PageParameters> getSelfRegInfo(final UserTO newUser)
throws JsonProcessingException {
-
- return Pair.of(Self.class, new PageParameters().add(Self.NEW_USER_PARAM, MAPPER.writeValueAsString(newUser)));
+ return Pair.of(SelfRegistration.class,
+ new PageParameters().add(SelfRegistration.NEW_USER_PARAM, MAPPER.writeValueAsString(newUser)));
}
}
diff --git a/ext/oidcc4ui/client-enduser/src/main/resources/org/apache/syncope/client/enduser/panels/OIDCSSOLoginFormPanel.html b/ext/oidcc4ui/client-enduser/src/main/resources/org/apache/syncope/client/enduser/panels/OIDCSSOLoginFormPanel.html
index ce0dbe8..9d4d6af 100644
--- a/ext/oidcc4ui/client-enduser/src/main/resources/org/apache/syncope/client/enduser/panels/OIDCSSOLoginFormPanel.html
+++ b/ext/oidcc4ui/client-enduser/src/main/resources/org/apache/syncope/client/enduser/panels/OIDCSSOLoginFormPanel.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
@@ -17,7 +18,9 @@
under the License.
-->
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
- <wicket:extend>
-
- </wicket:extend>
+ <wicket:panel>
+ <div class="form-group">
+ <span wicket:id="ops"></span>
+ </div>
+ </wicket:panel>
</html>
diff --git a/ext/saml2sp4ui/client-enduser/src/main/java/org/apache/syncope/client/enduser/panels/SAMLSSOLoginFormPanel.java b/ext/saml2sp4ui/client-enduser/src/main/java/org/apache/syncope/client/enduser/panels/SAMLSSOLoginFormPanel.java
index b94e979..ade3485 100644
--- a/ext/saml2sp4ui/client-enduser/src/main/java/org/apache/syncope/client/enduser/panels/SAMLSSOLoginFormPanel.java
+++ b/ext/saml2sp4ui/client-enduser/src/main/java/org/apache/syncope/client/enduser/panels/SAMLSSOLoginFormPanel.java
@@ -18,12 +18,12 @@
*/
package org.apache.syncope.client.enduser.panels;
-import org.apache.syncope.client.ui.commons.panels.AbstractSAMLSSOLoginFormPanel;
import org.apache.syncope.client.ui.commons.BaseSession;
+import org.apache.syncope.client.ui.commons.panels.AbstractSAMLSSOLoginFormPanel;
public class SAMLSSOLoginFormPanel extends AbstractSAMLSSOLoginFormPanel {
- private static final long serialVersionUID = 6825891694497952535L;
+ private static final long serialVersionUID = -5252094098970677128L;
public SAMLSSOLoginFormPanel(final String id, final BaseSession session) {
super(id, session);
diff --git a/ext/saml2sp4ui/client-enduser/src/main/java/org/apache/syncope/client/enduser/resources/EnduserAssertionConsumerResource.java b/ext/saml2sp4ui/client-enduser/src/main/java/org/apache/syncope/client/enduser/resources/EnduserAssertionConsumerResource.java
index a072111..2d74159 100644
--- a/ext/saml2sp4ui/client-enduser/src/main/java/org/apache/syncope/client/enduser/resources/EnduserAssertionConsumerResource.java
+++ b/ext/saml2sp4ui/client-enduser/src/main/java/org/apache/syncope/client/enduser/resources/EnduserAssertionConsumerResource.java
@@ -21,7 +21,7 @@
import com.fasterxml.jackson.core.JsonProcessingException;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.syncope.client.enduser.pages.SAML2SPLogin;
-import org.apache.syncope.client.enduser.pages.Self;
+import org.apache.syncope.client.enduser.pages.SelfRegistration;
import org.apache.syncope.client.ui.commons.SAML2SP4UIConstants;
import org.apache.syncope.client.ui.commons.annotations.Resource;
import org.apache.syncope.client.ui.commons.resources.saml2sp4ui.AssertionConsumerResource;
@@ -44,7 +44,7 @@
@Override
protected Pair<Class<? extends WebPage>, PageParameters> getSelfRegInfo(final UserTO newUser)
throws JsonProcessingException {
-
- return Pair.of(Self.class, new PageParameters().add(Self.NEW_USER_PARAM, MAPPER.writeValueAsString(newUser)));
+ return Pair.of(SelfRegistration.class,
+ new PageParameters().add(SelfRegistration.NEW_USER_PARAM, MAPPER.writeValueAsString(newUser)));
}
}
diff --git a/ext/saml2sp4ui/client-enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SAMLSSOLoginFormPanel.html b/ext/saml2sp4ui/client-enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SAMLSSOLoginFormPanel.html
index ce0dbe8..6290455 100644
--- a/ext/saml2sp4ui/client-enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SAMLSSOLoginFormPanel.html
+++ b/ext/saml2sp4ui/client-enduser/src/main/resources/org/apache/syncope/client/enduser/panels/SAMLSSOLoginFormPanel.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
@@ -17,7 +18,9 @@
under the License.
-->
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
- <wicket:extend>
-
- </wicket:extend>
+ <wicket:panel>
+ <div class="form-group">
+ <span wicket:id="idps"></span>
+ </div>
+ </wicket:panel>
</html>
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/ui/AbstractUITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractUITCase.java
similarity index 99%
rename from fit/core-reference/src/test/java/org/apache/syncope/fit/ui/AbstractUITCase.java
rename to fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractUITCase.java
index fa283fa..eed1c08 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/ui/AbstractUITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractUITCase.java
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.syncope.fit.ui;
+package org.apache.syncope.fit;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail;
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/AbstractConsoleITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/AbstractConsoleITCase.java
index 59575de..654d677 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/AbstractConsoleITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/AbstractConsoleITCase.java
@@ -41,7 +41,7 @@
import org.apache.syncope.common.keymaster.client.self.SelfKeymasterClientContext;
import org.apache.syncope.common.keymaster.client.zookeeper.ZookeeperKeymasterClientContext;
import org.apache.syncope.common.rest.api.service.SyncopeService;
-import org.apache.syncope.fit.ui.AbstractUITCase;
+import org.apache.syncope.fit.AbstractUITCase;
import org.apache.wicket.util.tester.FormTester;
import org.apache.wicket.util.tester.WicketTester;
import org.junit.jupiter.api.BeforeAll;
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/AbstractTypesITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/AbstractTypesITCase.java
index 787cd44..13fde09 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/AbstractTypesITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/AbstractTypesITCase.java
@@ -42,7 +42,7 @@
}
protected void browsingToRelationshipType() {
- TESTER.clickLink("body:configurationLI:configurationUL:typesLI:types");
+ TESTER.clickLink("body:configurationLI:configurationUL:typesLI:types", false);
TESTER.assertRenderedPage(Types.class);
TESTER.clickLink("body:content:tabbedPanel:tabs-container:tabs:0:link");
@@ -51,7 +51,7 @@
}
protected void browsingToAnyTypes() {
- TESTER.clickLink("body:configurationLI:configurationUL:typesLI:types");
+ TESTER.clickLink("body:configurationLI:configurationUL:typesLI:types", false);
TESTER.assertRenderedPage(Types.class);
TESTER.clickLink("body:content:tabbedPanel:tabs-container:tabs:1:link");
@@ -60,7 +60,7 @@
}
protected void browsingToAnyTypeClasses() {
- TESTER.clickLink("body:configurationLI:configurationUL:typesLI:types");
+ TESTER.clickLink("body:configurationLI:configurationUL:typesLI:types", false);
TESTER.assertRenderedPage(Types.class);
TESTER.clickLink("body:content:tabbedPanel:tabs-container:tabs:2:link");
@@ -69,7 +69,7 @@
}
protected void browsingToPlainSchemas() {
- TESTER.clickLink("body:configurationLI:configurationUL:typesLI:types");
+ TESTER.clickLink("body:configurationLI:configurationUL:typesLI:types", false);
TESTER.assertRenderedPage(Types.class);
TESTER.clickLink("body:content:tabbedPanel:tabs-container:tabs:3:link");
@@ -78,7 +78,7 @@
}
protected void browsingToVirtualSchemas() {
- TESTER.clickLink("body:configurationLI:configurationUL:typesLI:types");
+ TESTER.clickLink("body:configurationLI:configurationUL:typesLI:types", false);
TESTER.assertRenderedPage(Types.class);
TESTER.clickLink("body:content:tabbedPanel:tabs-container:tabs:3:link");
@@ -114,16 +114,14 @@
browsingToAnyTypeClasses();
TESTER.clickLink("body:content:tabbedPanel:panel:container:content:add");
- TESTER.assertComponent("body:content:tabbedPanel:panel:outerObjectsRepeater:0:outer",
- Modal.class);
+ TESTER.assertComponent("body:content:tabbedPanel:panel:outerObjectsRepeater:0:outer", Modal.class);
- final FormTester formTester = TESTER.newFormTester(
+ FormTester formTester = TESTER.newFormTester(
"body:content:tabbedPanel:panel:outerObjectsRepeater:0:outer:form");
formTester.setValue("content:anyTypeClassDetailsPanel:form:key:textField", name);
TESTER.clearFeedbackMessages();
- TESTER.clickLink(
- "body:content:tabbedPanel:panel:outerObjectsRepeater:0:outer:dialog:footer:inputs:0:submit");
+ TESTER.clickLink("body:content:tabbedPanel:panel:outerObjectsRepeater:0:outer:dialog:footer:inputs:0:submit");
assertSuccessMessage();
TESTER.clearFeedbackMessages();
}
@@ -132,15 +130,13 @@
browsingToAnyTypes();
TESTER.clickLink("body:content:tabbedPanel:panel:container:content:add");
- TESTER.assertComponent("body:content:tabbedPanel:panel:outerObjectsRepeater:0:outer",
- Modal.class);
+ TESTER.assertComponent("body:content:tabbedPanel:panel:outerObjectsRepeater:0:outer", Modal.class);
final FormTester formTester = TESTER.newFormTester(
"body:content:tabbedPanel:panel:outerObjectsRepeater:0:outer:form");
formTester.setValue("content:anyTypeDetailsPanel:container:form:key:textField", name);
- TESTER.clickLink(
- "body:content:tabbedPanel:panel:outerObjectsRepeater:0:outer:dialog:footer:inputs:0:submit");
+ TESTER.clickLink("body:content:tabbedPanel:panel:outerObjectsRepeater:0:outer:dialog:footer:inputs:0:submit");
assertSuccessMessage();
TESTER.clearFeedbackMessages();
}
@@ -150,8 +146,7 @@
TESTER.clickLink("body:content:tabbedPanel:panel:container:content:add");
- TESTER.assertComponent("body:content:tabbedPanel:panel:outerObjectsRepeater:0:outer",
- Modal.class);
+ TESTER.assertComponent("body:content:tabbedPanel:panel:outerObjectsRepeater:0:outer", Modal.class);
final FormTester formTester = TESTER.newFormTester(
"body:content:tabbedPanel:panel:outerObjectsRepeater:0:outer:form");
@@ -159,8 +154,7 @@
formTester.setValue(
"content:relationshipTypeDetails:container:form:description:textField", "test relationshipType");
- TESTER.clickLink(
- "body:content:tabbedPanel:panel:outerObjectsRepeater:0:outer:dialog:footer:inputs:0:submit");
+ TESTER.clickLink("body:content:tabbedPanel:panel:outerObjectsRepeater:0:outer:dialog:footer:inputs:0:submit");
assertSuccessMessage();
TESTER.clearFeedbackMessages();
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/AjaxBrowseITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/AjaxBrowseITCase.java
index 0347d60..e59aac8 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/AjaxBrowseITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/AjaxBrowseITCase.java
@@ -58,28 +58,28 @@
TESTER.assertRenderedPage(Dashboard.class);
- TESTER.clickLink("body:realmsLI:realms");
+ TESTER.clickLink("body:realmsLI:realms", false);
TESTER.assertRenderedPage(Realms.class);
- TESTER.clickLink("body:idmPages:0:idmPageLI:idmPage");
+ TESTER.clickLink("body:idmPages:0:idmPageLI:idmPage", false);
TESTER.assertRenderedPage(Topology.class);
- TESTER.clickLink("body:reportsLI:reports");
+ TESTER.clickLink("body:reportsLI:reports", false);
TESTER.assertRenderedPage(Reports.class);
- TESTER.clickLink("body:configurationLI:configurationUL:logsLI:logs");
+ TESTER.clickLink("body:configurationLI:configurationUL:logsLI:logs", false);
TESTER.assertRenderedPage(Logs.class);
- TESTER.clickLink("body:configurationLI:configurationUL:typesLI:types");
+ TESTER.clickLink("body:configurationLI:configurationUL:typesLI:types", false);
TESTER.assertRenderedPage(Types.class);
- TESTER.clickLink("body:configurationLI:configurationUL:securityLI:security");
+ TESTER.clickLink("body:configurationLI:configurationUL:securityLI:security", false);
TESTER.assertRenderedPage(Security.class);
- TESTER.clickLink("body:configurationLI:configurationUL:policiesLI:policies");
+ TESTER.clickLink("body:configurationLI:configurationUL:policiesLI:policies", false);
TESTER.assertRenderedPage(Policies.class);
- TESTER.clickLink("body:configurationLI:configurationUL:notificationsLI:notifications");
+ TESTER.clickLink("body:configurationLI:configurationUL:notificationsLI:notifications", false);
TESTER.assertRenderedPage(Notifications.class);
}
}
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/AnyObjectsITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/AnyObjectsITCase.java
index 140bbd3..2f53c30 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/AnyObjectsITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/AnyObjectsITCase.java
@@ -42,7 +42,7 @@
@Test
public void filteredSearch() {
- TESTER.clickLink("body:realmsLI:realms");
+ TESTER.clickLink("body:realmsLI:realms", false);
TESTER.clickLink("body:content:body:container:content:tabbedPanel:tabs-container:tabs:3:link");
@@ -62,7 +62,7 @@
@Test
public void clickToClonePrinter() {
- TESTER.clickLink("body:realmsLI:realms");
+ TESTER.clickLink("body:realmsLI:realms", false);
TESTER.clickLink("body:content:body:container:content:tabbedPanel:tabs-container:tabs:3:link");
Component component = findComponentByProp("key", CONTAINER
@@ -84,7 +84,7 @@
@Test
public void editPrinter() {
- TESTER.clickLink("body:realmsLI:realms");
+ TESTER.clickLink("body:realmsLI:realms", false);
TESTER.clickLink("body:content:body:container:content:tabbedPanel:tabs-container:tabs:3:link");
Component component = findComponentByProp("key", CONTAINER
@@ -136,7 +136,7 @@
@Test
public void checkDeletePrinterLink() {
- TESTER.clickLink("body:realmsLI:realms");
+ TESTER.clickLink("body:realmsLI:realms", false);
TESTER.clickLink("body:content:body:container:content:tabbedPanel:tabs-container:tabs:3:link");
Component component = findComponentByProp("key", CONTAINER
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/AnyTypeClassesITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/AnyTypeClassesITCase.java
index 02bb09a..538e308 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/AnyTypeClassesITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/AnyTypeClassesITCase.java
@@ -86,8 +86,8 @@
@Test
public void update() {
- final String plainSchema = "anyPlainSchema";
- final String name = "anyTypeClassToUpdate";
+ String plainSchema = "anyPlainSchema";
+ String name = "anyTypeClassToUpdate";
createAnyTypeClassWithoutSchema(name);
createPlainSchema(plainSchema);
browsingToAnyTypeClasses();
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/AnyTypesITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/AnyTypesITCase.java
index 63f4147..732f8bb 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/AnyTypesITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/AnyTypesITCase.java
@@ -87,7 +87,7 @@
TESTER.assertLabel(component.getPageRelativePath() + ":cells:3:cell", "[csv]");
// issue SYNCOPE-1111
- TESTER.clickLink("body:realmsLI:realms");
+ TESTER.clickLink("body:realmsLI:realms", false);
TESTER.assertRenderedPage(Realms.class);
TESTER.assertLabel(
"body:content:body:container:content:tabbedPanel:tabs-container:tabs:4:link:title",
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/BatchesITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/BatchesITCase.java
index 0021a28..05d5f43 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/BatchesITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/BatchesITCase.java
@@ -44,7 +44,7 @@
@Test
public void users() {
- TESTER.clickLink("body:realmsLI:realms");
+ TESTER.clickLink("body:realmsLI:realms", false);
TESTER.clickLink("body:content:body:container:content:tabbedPanel:tabs-container:tabs:1:link");
Component component = findComponentByProp("username", CONTAINER
@@ -69,7 +69,7 @@
@Test
public void userResource() {
- TESTER.clickLink("body:realmsLI:realms");
+ TESTER.clickLink("body:realmsLI:realms", false);
TESTER.clickLink("body:content:body:container:content:tabbedPanel:tabs-container:tabs:1:link");
Component component = findComponentByProp("username", CONTAINER
@@ -123,7 +123,7 @@
private static void userStatusBatch(final int index, final String resource) {
// suspend
- TESTER.clickLink("body:realmsLI:realms");
+ TESTER.clickLink("body:realmsLI:realms", false);
TESTER.clickLink("body:content:body:container:content:tabbedPanel:tabs-container:tabs:1:link");
Component component = findComponentByProp("username", CONTAINER
@@ -190,7 +190,7 @@
assertEquals(resource, StatusBean.class.cast(component.getDefaultModelObject()).getResource());
// re-activate
- TESTER.clickLink("body:realmsLI:realms");
+ TESTER.clickLink("body:realmsLI:realms", false);
TESTER.clickLink("body:content:body:container:content:tabbedPanel:tabs-container:tabs:1:link");
component = findComponentByProp("username", CONTAINER
@@ -254,7 +254,7 @@
@Test
public void groupResource() {
- TESTER.clickLink("body:realmsLI:realms");
+ TESTER.clickLink("body:realmsLI:realms", false);
TESTER.clickLink("body:content:body:container:content:tabbedPanel:tabs-container:tabs:2:link");
Component component = findComponentByProp("name", CONTAINER
@@ -303,7 +303,7 @@
@Test
public void printerResource() {
- TESTER.clickLink("body:realmsLI:realms");
+ TESTER.clickLink("body:realmsLI:realms", false);
TESTER.clickLink("body:content:body:container:content:tabbedPanel:tabs-container:tabs:3:link");
Component component = findComponentByProp("key", CONTAINER
@@ -353,7 +353,7 @@
@Test
public void executePropagationTask() {
- TESTER.clickLink("body:idmPages:0:idmPageLI:idmPage");
+ TESTER.clickLink("body:idmPages:0:idmPageLI:idmPage", false);
Component component = findComponentByProp("key", "body:resources", "resource-testdb");
assertNotNull(component);
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/DisplayAttributesITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/DisplayAttributesITCase.java
index dbce025..b3ac491 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/DisplayAttributesITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/DisplayAttributesITCase.java
@@ -29,7 +29,7 @@
@BeforeEach
public void login() {
doLogin(ADMIN_UNAME, ADMIN_PWD);
- TESTER.clickLink("body:realmsLI:realms");
+ TESTER.clickLink("body:realmsLI:realms", false);
TESTER.assertRenderedPage(Realms.class);
}
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/GroupsITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/GroupsITCase.java
index 7601f5e..4c2c900 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/GroupsITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/GroupsITCase.java
@@ -44,7 +44,7 @@
@Test
public void read() {
- TESTER.clickLink("body:realmsLI:realms");
+ TESTER.clickLink("body:realmsLI:realms", false);
TESTER.clickLink("body:content:body:container:content:tabbedPanel:tabs-container:tabs:2:link");
Component component = findComponentByProp("name", CONTAINER
@@ -74,7 +74,7 @@
@Test
public void filteredSearch() {
- TESTER.clickLink("body:realmsLI:realms");
+ TESTER.clickLink("body:realmsLI:realms", false);
TESTER.clickLink("body:content:body:container:content:tabbedPanel:tabs-container:tabs:2:link");
TESTER.clickLink(
@@ -92,7 +92,7 @@
}
private static void cloneGroup(final String group) {
- TESTER.clickLink("body:realmsLI:realms");
+ TESTER.clickLink("body:realmsLI:realms", false);
TESTER.clickLink("body:content:body:container:content:tabbedPanel:tabs-container:tabs:2:link");
Component component = findComponentByProp("name", CONTAINER
@@ -245,7 +245,7 @@
@Test
public void checkDeleteGroupLink() {
- TESTER.clickLink("body:realmsLI:realms");
+ TESTER.clickLink("body:realmsLI:realms", false);
TESTER.clickLink("body:content:body:container:content:tabbedPanel:tabs-container:tabs:2:link");
Component component = findComponentByProp("name", CONTAINER
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/LinkedAccountsITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/LinkedAccountsITCase.java
index fac17db..7beb2f5 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/LinkedAccountsITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/LinkedAccountsITCase.java
@@ -102,7 +102,7 @@
public void cleanUp() {
try {
SyncopeConsoleSession.get().getService(UserService.class).delete(user.getKey());
- } catch (final SyncopeClientException e) {
+ } catch (SyncopeClientException e) {
if (e.getType() != ClientExceptionType.NotFound) {
throw e;
}
@@ -112,7 +112,7 @@
@Test
public void createLinkedAccountAndMergeWithUser() {
// Locate and select first user
- TESTER.clickLink("body:realmsLI:realms");
+ TESTER.clickLink("body:realmsLI:realms", false);
TESTER.clickLink("body:content:body:container:content:tabbedPanel:tabs-container:tabs:1:link");
Component verdiUserComponent = findComponentByProp("username", CONTAINER
@@ -183,10 +183,8 @@
try {
userService.read(user.getKey());
fail("User must have been deleted; expect an exception here");
- } catch (final SyncopeClientException e) {
- if (e.getType() != ClientExceptionType.NotFound) {
- fail(e.getMessage());
- }
+ } catch (SyncopeClientException e) {
+ assertEquals(ClientExceptionType.NotFound, e.getType());
}
// User must include merged accounts now
UserTO verdi = userService.read("verdi");
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/LogsITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/LogsITCase.java
index 281d714..b2131c5 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/LogsITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/LogsITCase.java
@@ -42,7 +42,7 @@
@BeforeEach
public void login() {
doLogin(ADMIN_UNAME, ADMIN_PWD);
- TESTER.clickLink("body:configurationLI:configurationUL:logsLI:logs");
+ TESTER.clickLink("body:configurationLI:configurationUL:logsLI:logs", false);
TESTER.assertRenderedPage(Logs.class);
}
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/NotificationsITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/NotificationsITCase.java
index d059d04..118513f 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/NotificationsITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/NotificationsITCase.java
@@ -35,7 +35,7 @@
@BeforeEach
public void login() {
doLogin(ADMIN_UNAME, ADMIN_PWD);
- TESTER.clickLink("body:configurationLI:configurationUL:notificationsLI:notifications");
+ TESTER.clickLink("body:configurationLI:configurationUL:notificationsLI:notifications", false);
TESTER.assertRenderedPage(Notifications.class);
}
@@ -110,7 +110,7 @@
formTester.submit("content:form:buttons:finish");
assertSuccessMessage();
TESTER.cleanupFeedbackMessages();
- TESTER.clickLink("body:configurationLI:configurationUL:notificationsLI:notifications");
+ TESTER.clickLink("body:configurationLI:configurationUL:notificationsLI:notifications", false);
}
@Test
@@ -147,7 +147,7 @@
@Test
public void execute() {
- TESTER.clickLink("body:configurationLI:configurationUL:notificationsLI:notifications");
+ TESTER.clickLink("body:configurationLI:configurationUL:notificationsLI:notifications", false);
Component result = findComponentByProp("subject",
"body:content:tabbedPanel:panel:container:content:searchContainer:resultTable:tablePanel:groupForm:"
@@ -178,7 +178,7 @@
assertSuccessMessage();
TESTER.cleanupFeedbackMessages();
- TESTER.clickLink("body:configurationLI:configurationUL:notificationsLI:notifications");
+ TESTER.clickLink("body:configurationLI:configurationUL:notificationsLI:notifications", false);
result = findComponentByProp("subject", "body:content:tabbedPanel:panel:container:content:"
+ "searchContainer:resultTable:tablePanel:groupForm:checkgroup:dataTable", "Password Reset request");
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/ParametersITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/ParametersITCase.java
index 26fd172..309664c 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/ParametersITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/ParametersITCase.java
@@ -34,7 +34,7 @@
@BeforeEach
public void login() {
doLogin(ADMIN_UNAME, ADMIN_PWD);
- TESTER.clickLink("body:keymasterLI:keymasterUL:parametersLI:parameters");
+ TESTER.clickLink("body:keymasterLI:keymasterUL:parametersLI:parameters", false);
TESTER.assertRenderedPage(Parameters.class);
}
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/PoliciesITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/PoliciesITCase.java
index 708e31e..7e37ba2 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/PoliciesITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/PoliciesITCase.java
@@ -37,7 +37,7 @@
@BeforeEach
public void login() {
doLogin(ADMIN_UNAME, ADMIN_PWD);
- TESTER.clickLink("body:configurationLI:configurationUL:policiesLI:policies");
+ TESTER.clickLink("body:configurationLI:configurationUL:policiesLI:policies", false);
TESTER.assertRenderedPage(Policies.class);
}
@@ -741,7 +741,7 @@
composeDefaultAccountPolicy(name);
// goto realms
- TESTER.clickLink("body:realmsLI:realms");
+ TESTER.clickLink("body:realmsLI:realms", false);
TESTER.assertRenderedPage(Realms.class);
// edit root realm
@@ -844,7 +844,7 @@
assertNull(component);
// delete default policy
- TESTER.clickLink("body:configurationLI:configurationUL:policiesLI:policies");
+ TESTER.clickLink("body:configurationLI:configurationUL:policiesLI:policies", false);
TESTER.assertRenderedPage(Policies.class);
deleteAccountPolicy(name);
}
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/RealmsITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/RealmsITCase.java
index 8b4df01..a77eae8 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/RealmsITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/RealmsITCase.java
@@ -34,7 +34,7 @@
@BeforeEach
public void login() {
doLogin(ADMIN_UNAME, ADMIN_PWD);
- TESTER.clickLink("body:realmsLI:realms");
+ TESTER.clickLink("body:realmsLI:realms", false);
TESTER.assertRenderedPage(Realms.class);
}
@@ -65,7 +65,7 @@
+ "0:action:action", Constants.ON_CLICK);
// remove the new realm just created
- TESTER.clickLink("body:realmsLI:realms");
+ TESTER.clickLink("body:realmsLI:realms", false);
TESTER.executeAjaxEvent(
"body:content:realmChoicePanel:container:realmsFragment:realms:btn", Constants.ON_CLICK);
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/ReportsITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/ReportsITCase.java
index 04e1a5d..c1766d2 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/ReportsITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/ReportsITCase.java
@@ -35,7 +35,7 @@
@BeforeEach
public void login() {
doLogin(ADMIN_UNAME, ADMIN_PWD);
- TESTER.clickLink("body:reportsLI:reports");
+ TESTER.clickLink("body:reportsLI:reports", false);
TESTER.assertRenderedPage(Reports.class);
}
@@ -63,11 +63,11 @@
assertSuccessMessage();
TESTER.cleanupFeedbackMessages();
- TESTER.clickLink("body:reportsLI:reports");
+ TESTER.clickLink("body:reportsLI:reports", false);
}
private static void delete(final String name) {
- TESTER.clickLink("body:reportsLI:reports");
+ TESTER.clickLink("body:reportsLI:reports", false);
Component result = findComponentByProp(
"name", "body:content:tabbedPanel:panel:firstLevelContainer:first:container:"
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/RolesITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/RolesITCase.java
index c3d350d..93d02c8 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/RolesITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/RolesITCase.java
@@ -34,7 +34,7 @@
@BeforeEach
public void login() {
doLogin(ADMIN_UNAME, ADMIN_PWD);
- TESTER.clickLink("body:configurationLI:configurationUL:securityLI:security");
+ TESTER.clickLink("body:configurationLI:configurationUL:securityLI:security", false);
TESTER.assertRenderedPage(Security.class);
}
@@ -70,7 +70,7 @@
assertSuccessMessage();
TESTER.cleanupFeedbackMessages();
- TESTER.clickLink("body:configurationLI:configurationUL:securityLI:security");
+ TESTER.clickLink("body:configurationLI:configurationUL:securityLI:security", false);
}
@Test
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/SecurityQuestionsITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/SecurityQuestionsITCase.java
index c8c0d25..e37a24f 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/SecurityQuestionsITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/SecurityQuestionsITCase.java
@@ -37,7 +37,7 @@
@BeforeEach
public void login() {
doLogin(ADMIN_UNAME, ADMIN_PWD);
- TESTER.clickLink("body:configurationLI:configurationUL:securityLI:security");
+ TESTER.clickLink("body:configurationLI:configurationUL:securityLI:security", false);
TESTER.assertRenderedPage(Security.class);
TESTER.clickLink("body:content:tabbedPanel:tabs-container:tabs:4:link");
}
@@ -59,7 +59,7 @@
assertSuccessMessage();
TESTER.cleanupFeedbackMessages();
- TESTER.clickLink("body:configurationLI:configurationUL:securityLI:security");
+ TESTER.clickLink("body:configurationLI:configurationUL:securityLI:security", false);
TESTER.clickLink("body:content:tabbedPanel:tabs-container:tabs:4:link");
}
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/TopologyITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/TopologyITCase.java
index 88556b9..a764406 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/TopologyITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/TopologyITCase.java
@@ -43,7 +43,7 @@
@BeforeEach
public void login() {
doLogin(ADMIN_UNAME, ADMIN_PWD);
- TESTER.clickLink("body:idmPages:0:idmPageLI:idmPage");
+ TESTER.clickLink("body:idmPages:0:idmPageLI:idmPage", false);
TESTER.assertRenderedPage(Topology.class);
}
@@ -184,7 +184,7 @@
assertSuccessMessage();
TESTER.cleanupFeedbackMessages();
- TESTER.clickLink("body:idmPages:0:idmPageLI:idmPage");
+ TESTER.clickLink("body:idmPages:0:idmPageLI:idmPage", false);
Component component = findComponentByProp("key", "body:resources", res);
assertNotNull(component);
@@ -289,7 +289,7 @@
assertSuccessMessage();
TESTER.cleanupFeedbackMessages();
- TESTER.clickLink("body:idmPages:0:idmPageLI:idmPage");
+ TESTER.clickLink("body:idmPages:0:idmPageLI:idmPage", false);
component = findComponentByProp("key", "body:resources", res);
assertNull(component);
}
@@ -397,7 +397,7 @@
+ "outerObjectsRepeater:1:outer:container:content:togglePanelContainer:container:"
+ "actions:actions:actionRepeater:2:action:action");
- TESTER.clickLink("body:idmPages:0:idmPageLI:idmPage");
+ TESTER.clickLink("body:idmPages:0:idmPageLI:idmPage", false);
component = findComponentByProp("key", "body:resources", "resource-testdb");
assertNotNull(component);
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/UsersITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/UsersITCase.java
index 7a922b8..3f116dd 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/UsersITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/UsersITCase.java
@@ -45,7 +45,7 @@
@Test
public void filteredSearch() {
- TESTER.clickLink("body:realmsLI:realms");
+ TESTER.clickLink("body:realmsLI:realms", false);
TESTER.clickLink("body:content:body:container:content:tabbedPanel:tabs-container:tabs:1:link");
TESTER.clickLink(
@@ -68,7 +68,7 @@
@Test
public void forceChangePassword() {
- TESTER.clickLink("body:realmsLI:realms");
+ TESTER.clickLink("body:realmsLI:realms", false);
TESTER.clickLink("body:content:body:container:content:tabbedPanel:tabs-container:tabs:1:link");
Component component = findComponentByProp("username", CONTAINER
@@ -85,7 +85,7 @@
@Test
public void clickToCloneUser() {
- TESTER.clickLink("body:realmsLI:realms");
+ TESTER.clickLink("body:realmsLI:realms", false);
TESTER.clickLink("body:content:body:container:content:tabbedPanel:tabs-container:tabs:1:link");
Component component = findComponentByProp("username", CONTAINER
@@ -109,7 +109,7 @@
@Test
public void editRelationships() {
- TESTER.clickLink("body:realmsLI:realms");
+ TESTER.clickLink("body:realmsLI:realms", false);
TESTER.clickLink("body:content:body:container:content:tabbedPanel:tabs-container:tabs:1:link");
Component component = findComponentByProp("username", CONTAINER
@@ -189,7 +189,7 @@
@Test
public void editUser() {
- TESTER.clickLink("body:realmsLI:realms");
+ TESTER.clickLink("body:realmsLI:realms", false);
TESTER.clickLink("body:content:body:container:content:tabbedPanel:tabs-container:tabs:1:link");
Component component = findComponentByProp("username", CONTAINER
@@ -255,7 +255,7 @@
@Test
public void editUserMembership() {
- TESTER.clickLink("body:realmsLI:realms");
+ TESTER.clickLink("body:realmsLI:realms", false);
TESTER.executeAjaxEvent("body:content:realmChoicePanel:container"
+ ":realmsFragment:realms:btn", Constants.ON_CLICK);
TESTER.executeAjaxEvent("body:content:realmChoicePanel:container"
@@ -349,7 +349,7 @@
@Test
public void editUserMemberships() {
- TESTER.clickLink("body:realmsLI:realms");
+ TESTER.clickLink("body:realmsLI:realms", false);
TESTER.executeAjaxEvent("body:content:realmChoicePanel:container"
+ ":realmsFragment:realms:btn", Constants.ON_CLICK);
TESTER.executeAjaxEvent("body:content:realmChoicePanel:container"
@@ -571,7 +571,7 @@
@Test
public void checkDeleteUsrLink() {
- TESTER.clickLink("body:realmsLI:realms");
+ TESTER.clickLink("body:realmsLI:realms", false);
TESTER.clickLink("body:content:body:container:content:tabbedPanel:tabs-container:tabs:1:link");
Component component = findComponentByProp("username", CONTAINER
@@ -586,7 +586,7 @@
@Test
public void editDateTimeField() {
- TESTER.clickLink("body:realmsLI:realms");
+ TESTER.clickLink("body:realmsLI:realms", false);
TESTER.clickLink("body:content:body:container:content:tabbedPanel:tabs-container:tabs:1:link");
Component component = findComponentByProp("username", CONTAINER
@@ -679,7 +679,7 @@
public void changePassword() {
TESTER.cleanupFeedbackMessages();
- TESTER.clickLink("body:realmsLI:realms");
+ TESTER.clickLink("body:realmsLI:realms", false);
TESTER.clickLink("body:content:body:container:content:tabbedPanel:tabs-container:tabs:1:link");
Component component = findComponentByProp("username", CONTAINER
@@ -705,7 +705,7 @@
assertSuccessMessage();
TESTER.cleanupFeedbackMessages();
- TESTER.clickLink("body:realmsLI:realms");
+ TESTER.clickLink("body:realmsLI:realms", false);
TESTER.clickLink("body:content:body:container:content:tabbedPanel:tabs-container:tabs:1:link");
component = findComponentByProp("username", CONTAINER
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PlainSchemaITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PlainSchemaITCase.java
index 1d66c02..0f643cc 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PlainSchemaITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PlainSchemaITCase.java
@@ -184,58 +184,65 @@
UserTO userTO = createUser(userCR).getEntity();
assertNotNull(userTO);
-
- UserUR userUR = new UserUR();
- userUR.setKey(userTO.getKey());
- // validation OK - application/pdf -> application/pdf
- userUR.getPlainAttrs().add(new AttrPatch.Builder(attr("BinaryPDF",
- Base64.getEncoder().encodeToString(
- IOUtils.readBytesFromStream(getClass().getResourceAsStream("/test.pdf"))))).
- operation(PatchOperation.ADD_REPLACE).
- build());
-
- updateUser(userUR);
- assertNotNull(userService.read(userTO.getKey()).getPlainAttr("BinaryPDF"));
-
- userUR = new UserUR();
- userUR.setKey(userTO.getKey());
- // validation KO - text/html -> application/pdf
try {
+ UserUR userUR = new UserUR();
+ userUR.setKey(userTO.getKey());
+ // validation OK - application/pdf -> application/pdf
userUR.getPlainAttrs().add(new AttrPatch.Builder(attr("BinaryPDF",
Base64.getEncoder().encodeToString(
- IOUtils.readBytesFromStream(getClass().getResourceAsStream("/test.html"))))).
+ IOUtils.readBytesFromStream(getClass().getResourceAsStream("/test.pdf"))))).
operation(PatchOperation.ADD_REPLACE).
build());
updateUser(userUR);
- fail("This should not be reacheable");
- } catch (SyncopeClientException e) {
- assertEquals(ClientExceptionType.InvalidValues, e.getType());
+ assertNotNull(userService.read(userTO.getKey()).getPlainAttr("BinaryPDF"));
+
+ userUR = new UserUR();
+ userUR.setKey(userTO.getKey());
+ // validation KO - text/html -> application/pdf
+ try {
+ userUR.getPlainAttrs().add(new AttrPatch.Builder(attr("BinaryPDF",
+ Base64.getEncoder().encodeToString(
+ IOUtils.readBytesFromStream(getClass().getResourceAsStream("/test.html"))))).
+ operation(PatchOperation.ADD_REPLACE).
+ build());
+
+ updateUser(userUR);
+ fail("This should not be reacheable");
+ } catch (SyncopeClientException e) {
+ assertEquals(ClientExceptionType.InvalidValues, e.getType());
+ }
+
+ userUR = new UserUR();
+ userUR.setKey(userTO.getKey());
+ // validation ok - application/json -> application/json
+ userUR.getPlainAttrs().add(new AttrPatch.Builder(attr("BinaryJSON",
+ Base64.getEncoder().encodeToString(
+ IOUtils.readBytesFromStream(getClass().getResourceAsStream("/test.json"))))).
+ operation(PatchOperation.ADD_REPLACE).
+ build());
+
+ updateUser(userUR);
+ assertNotNull(userService.read(userTO.getKey()).getPlainAttr("BinaryJSON"));
+
+ userUR = new UserUR();
+ userUR.setKey(userTO.getKey());
+ // no validation - application/xml -> application/json
+ userUR.getPlainAttrs().add(new AttrPatch.Builder(attr("BinaryJSON2",
+ Base64.getEncoder().encodeToString(
+ IOUtils.readBytesFromStream(getClass().getResourceAsStream("/test.xml"))))).
+ operation(PatchOperation.ADD_REPLACE).
+ build());
+
+ updateUser(userUR);
+ assertNotNull(userService.read(userTO.getKey()).getPlainAttr("BinaryJSON2"));
+ } finally {
+ userService.delete(userTO.getKey());
+
+ schemaService.delete(SchemaType.PLAIN, schemaTOpdf.getKey());
+ schemaService.delete(SchemaType.PLAIN, schemaTOjson.getKey());
+ schemaService.delete(SchemaType.PLAIN, schemaTOjson2.getKey());
}
-
- userUR = new UserUR();
- userUR.setKey(userTO.getKey());
- // validation ok - application/json -> application/json
- userUR.getPlainAttrs().add(new AttrPatch.Builder(attr("BinaryJSON",
- Base64.getEncoder().encodeToString(
- IOUtils.readBytesFromStream(getClass().getResourceAsStream("/test.json"))))).
- operation(PatchOperation.ADD_REPLACE).
- build());
-
- updateUser(userUR);
- assertNotNull(userService.read(userTO.getKey()).getPlainAttr("BinaryJSON"));
-
- userUR = new UserUR();
- userUR.setKey(userTO.getKey());
- // no validation - application/xml -> application/json
- userUR.getPlainAttrs().add(new AttrPatch.Builder(attr("BinaryJSON2",
- Base64.getEncoder().encodeToString(
- IOUtils.readBytesFromStream(getClass().getResourceAsStream("/test.xml"))))).
- operation(PatchOperation.ADD_REPLACE).
- build());
-
- updateUser(userUR);
- assertNotNull(userService.read(userTO.getKey()).getPlainAttr("BinaryJSON2"));
}
@Test
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PropagationTaskITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PropagationTaskITCase.java
index 1637720..b5acc24 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PropagationTaskITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PropagationTaskITCase.java
@@ -494,6 +494,7 @@
assertNotNull(schemaTO);
ResourceTO ldap = resourceService.read(RESOURCE_NAME_LDAP);
+ UserTO userTO = null;
try {
// 1. clone the LDAP resource and add some sensible mappings
ProvisionTO provisionGroup =
@@ -522,7 +523,7 @@
// 1. create group with the new resource assigned
GroupCR groupCR = new GroupCR();
groupCR.setName("SYNCOPEGROUP1473-" + getUUIDString());
- groupCR.setRealm("/");
+ groupCR.setRealm(SyncopeConstants.ROOT_REALM);
groupCR.getResources().add(ldap.getKey());
GroupTO groupTO = createGroup(groupCR).getEntity();
@@ -534,7 +535,7 @@
userCR.getResources().add(ldap.getKey());
userCR.getMemberships().add(new MembershipTO.Builder(groupTO.getKey()).build());
- UserTO userTO = createUser(userCR).getEntity();
+ userTO = createUser(userCR).getEntity();
assertNotNull(userTO);
// 3. check attributes prepared for propagation
@@ -571,6 +572,10 @@
} finally {
try {
resourceService.delete(ldap.getKey());
+ if (userTO != null) {
+ userService.delete(userTO.getKey());
+ }
+ schemaService.delete(SchemaType.PLAIN, schemaTO.getKey());
} catch (Exception ignore) {
// ignore
}
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/enduser/AbstractEnduserITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/enduser/AbstractEnduserITCase.java
index 43f8288..1d5ea14 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/enduser/AbstractEnduserITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/enduser/AbstractEnduserITCase.java
@@ -23,10 +23,6 @@
import com.giffing.wicket.spring.boot.starter.app.classscanner.candidates.WicketClassCandidatesHolder;
import com.giffing.wicket.spring.boot.starter.configuration.extensions.core.settings.general.GeneralSettingsProperties;
import com.giffing.wicket.spring.boot.starter.configuration.extensions.external.spring.boot.actuator.WicketEndpointRepositoryDefault;
-import java.util.Date;
-import java.util.List;
-import java.util.Locale;
-import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.syncope.client.enduser.SyncopeWebApplication;
import org.apache.syncope.client.enduser.commons.PreviewUtils;
@@ -36,35 +32,30 @@
import org.apache.syncope.client.lib.SyncopeClientFactoryBean;
import org.apache.syncope.client.ui.commons.ApplicationContextProvider;
import org.apache.syncope.client.ui.commons.MIMETypesLoader;
-import org.apache.syncope.common.rest.api.service.SyncopeService;
import org.apache.syncope.common.keymaster.client.self.SelfKeymasterClientContext;
import org.apache.syncope.common.keymaster.client.zookeeper.ZookeeperKeymasterClientContext;
import org.apache.syncope.common.lib.Attr;
import org.apache.syncope.common.lib.SyncopeConstants;
import org.apache.syncope.common.lib.request.UserCR;
+import org.apache.syncope.common.rest.api.beans.AnyQuery;
import org.apache.syncope.common.rest.api.service.SecurityQuestionService;
+import org.apache.syncope.common.rest.api.service.SyncopeService;
import org.apache.syncope.common.rest.api.service.UserService;
-import org.apache.syncope.fit.ui.AbstractUITCase;
+import org.apache.syncope.fit.AbstractUITCase;
import org.apache.wicket.util.tester.FormTester;
import org.apache.wicket.util.tester.WicketTester;
+import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
public abstract class AbstractEnduserITCase extends AbstractUITCase {
- protected static final String ENV_KEY_CONTENT_TYPE = "jaxrsContentType";
-
- protected static SyncopeClientFactoryBean clientFactory;
-
- protected static SyncopeClient adminClient;
-
- protected static UserService userService;
-
- protected static SecurityQuestionService securityQuestionService;
-
@ImportAutoConfiguration(classes = { SelfKeymasterClientContext.class, ZookeeperKeymasterClientContext.class })
@Configuration
public static class SyncopeEnduserWebApplicationTestConfig {
@@ -114,6 +105,14 @@
}
}
+ protected static SyncopeClientFactoryBean clientFactory;
+
+ protected static SyncopeClient adminClient;
+
+ protected static UserService userService;
+
+ protected static SecurityQuestionService securityQuestionService;
+
@BeforeAll
public static void setUp() {
Locale.setDefault(Locale.ENGLISH);
@@ -133,11 +132,6 @@
@BeforeAll
public static void restSetup() {
clientFactory = new SyncopeClientFactoryBean().setAddress(ADDRESS);
-
- String envContentType = System.getProperty(ENV_KEY_CONTENT_TYPE);
- if (StringUtils.isNotBlank(envContentType)) {
- clientFactory.setContentType(envContentType);
- }
LOG.info("Performing IT with content type {}", clientFactory.getContentType().getMediaType());
adminClient = clientFactory.create(ADMIN_UNAME, ADMIN_PWD);
@@ -182,7 +176,17 @@
securityQuestionService = adminClient.getService(SecurityQuestionService.class);
}
- protected void doLogin(final String user, final String passwd) {
+ @AfterAll
+ public static void cleanUp() {
+ userService.search(new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
+ fiql(SyncopeClient.getUserSearchConditionBuilder().
+ is("username").equalTo("selfupdate").
+ or("username").equalTo("selfpwdreset").
+ or("username").equalTo("mustchangepassword").query()).
+ build()).getResult().forEach(user -> userService.delete(user.getKey()));
+ }
+
+ protected static void doLogin(final String user, final String passwd) {
TESTER.startPage(Login.class);
TESTER.assertRenderedPage(Login.class);
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/enduser/AnonymousITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/enduser/AnonymousITCase.java
new file mode 100644
index 0000000..2d22b27
--- /dev/null
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/enduser/AnonymousITCase.java
@@ -0,0 +1,154 @@
+/*
+ * 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.fit.enduser;
+
+import static org.apache.syncope.fit.enduser.AbstractEnduserITCase.securityQuestionService;
+import static org.apache.syncope.fit.enduser.AbstractEnduserITCase.userService;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+import org.apache.syncope.client.enduser.pages.Login;
+import org.apache.syncope.client.enduser.pages.SelfPasswordReset;
+import org.apache.syncope.client.enduser.pages.SelfRegistration;
+import org.apache.syncope.client.enduser.pages.SelfResult;
+import org.apache.syncope.client.lib.SyncopeClient;
+import org.apache.syncope.client.ui.commons.Constants;
+import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.lib.request.StringReplacePatchItem;
+import org.apache.syncope.common.lib.request.UserUR;
+import org.apache.syncope.common.lib.to.SecurityQuestionTO;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.common.rest.api.beans.AnyQuery;
+import org.apache.wicket.util.tester.FormTester;
+import org.junit.jupiter.api.Test;
+
+public class AnonymousITCase extends AbstractEnduserITCase {
+
+ @Test
+ public void selfCreate() {
+ String username = "testUser";
+
+ TESTER.startPage(Login.class);
+ TESTER.assertRenderedPage(Login.class);
+
+ TESTER.clickLink("self-registration");
+ TESTER.assertRenderedPage(SelfRegistration.class);
+
+ String form = "body:contentWrapper:content:selfRegistrationPanel:form";
+ FormTester formTester = TESTER.newFormTester(form);
+
+ formTester.setValue("userDetailsPanelCard:contentPanel:username:textField", username);
+
+ formTester.setValue(
+ "userDetailsPanelCard:contentPanel:password:passwordPanel:passwordInnerForm:password:passwordField",
+ "Password123");
+ formTester.setValue(
+ "userDetailsPanelCard:contentPanel:password:passwordPanel:passwordInnerForm:confirmPassword:"
+ + "passwordField",
+ "Password123");
+
+ formTester.setValue(
+ "plainAttrsPanelCard:contentPanel:plainSchemas:schemas:6:panel:textField",
+ "Fullname");
+
+ formTester.setValue(
+ "plainAttrsPanelCard:contentPanel:plainSchemas:schemas:12:panel:textField",
+ "Surname");
+
+ formTester.setValue(
+ "plainAttrsPanelCard:contentPanel:plainSchemas:schemas:14:panel:textField",
+ username + "@syncope.apache.org");
+
+ try {
+ TESTER.executeAjaxEvent(form + ":submit", Constants.ON_CLICK);
+
+ TESTER.assertRenderedPage(SelfResult.class);
+
+ assertFalse(userService.search(new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
+ fiql(SyncopeClient.getUserSearchConditionBuilder().is("username").equalTo(username).query()).
+ build()).getResult().isEmpty());
+
+ assertNotNull(userService.read(username));
+
+ TESTER.cleanupFeedbackMessages();
+ } finally {
+ // cleanup
+ try {
+ userService.delete(username);
+ } catch (Exception e) {
+ // ignore
+ }
+ }
+ }
+
+ @Test
+ public void selfPasswordReset() {
+ SecurityQuestionTO question = securityQuestionService.read("887028ea-66fc-41e7-b397-620d7ea6dfbb");
+
+ UserTO selfpwdreset = userService.read("selfpwdreset");
+ userService.update(new UserUR.Builder(selfpwdreset.getKey()).
+ securityQuestion(new StringReplacePatchItem.Builder().value(question.getKey()).build()).
+ securityAnswer(new StringReplacePatchItem.Builder().value("ananswer").build()).
+ build());
+
+ TESTER.startPage(Login.class);
+ TESTER.assertRenderedPage(Login.class);
+
+ TESTER.clickLink("self-pwd-reset");
+
+ TESTER.assertRenderedPage(SelfPasswordReset.class);
+
+ String pwdResetForm = "body:contentWrapper:content:selfPwdResetForm";
+ FormTester formTester = TESTER.newFormTester(pwdResetForm);
+
+ // 1. set username to selfpwdreset
+ formTester.setValue("selfPasswordResetPanelCard:contentPanel:username", "selfpwdreset");
+ TESTER.executeAjaxEvent(
+ pwdResetForm + ":selfPasswordResetPanelCard:contentPanel:username", Constants.ON_BLUR);
+
+ // 2. check that the question has been populated
+ TESTER.assertModelValue(
+ pwdResetForm + ":selfPasswordResetPanelCard:contentPanel:securityQuestion",
+ question.getContent());
+
+ // 3. submit form and receive an error
+ TESTER.executeAjaxEvent(pwdResetForm + ":submit", Constants.ON_CLICK);
+ TESTER.assertErrorMessages("Invalid Security Answer");
+ TESTER.cleanupFeedbackMessages();
+
+ // 3.1 set the correct answer
+ formTester = TESTER.newFormTester(pwdResetForm);
+ formTester.setValue("selfPasswordResetPanelCard:contentPanel:username", "selfpwdreset");
+ TESTER.executeAjaxEvent(
+ pwdResetForm + ":selfPasswordResetPanelCard:contentPanel:username", Constants.ON_BLUR);
+ TESTER.assertModelValue(
+ pwdResetForm + ":selfPasswordResetPanelCard:contentPanel:securityQuestion",
+ question.getContent());
+ formTester.setValue("selfPasswordResetPanelCard:contentPanel:securityAnswer", "ananswer");
+ TESTER.executeAjaxEvent(
+ pwdResetForm + ":selfPasswordResetPanelCard:contentPanel:securityAnswer", Constants.ON_CHANGE);
+
+ // 4. submit form
+ TESTER.executeAjaxEvent(pwdResetForm + ":submit", Constants.ON_CLICK);
+
+ TESTER.assertRenderedPage(SelfResult.class);
+
+ TESTER.cleanupFeedbackMessages();
+ }
+}
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/enduser/AuthenticatedITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/enduser/AuthenticatedITCase.java
new file mode 100644
index 0000000..2ac7f98
--- /dev/null
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/enduser/AuthenticatedITCase.java
@@ -0,0 +1,122 @@
+/*
+ * 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.fit.enduser;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+import java.io.IOException;
+import org.apache.syncope.client.enduser.pages.Dashboard;
+import org.apache.syncope.client.enduser.pages.EditUser;
+import org.apache.syncope.client.enduser.pages.Login;
+import org.apache.syncope.client.enduser.pages.MustChangePassword;
+import org.apache.syncope.client.enduser.pages.SelfResult;
+import org.apache.syncope.client.ui.commons.Constants;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxPasswordFieldPanel;
+import org.apache.syncope.common.lib.request.BooleanReplacePatchItem;
+import org.apache.syncope.common.lib.request.UserUR;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.fit.FlowableDetector;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.util.tester.FormTester;
+import org.junit.jupiter.api.Test;
+
+public class AuthenticatedITCase extends AbstractEnduserITCase {
+
+ @Test
+ public void login() throws IOException {
+ TESTER.startPage(Login.class);
+ TESTER.assertRenderedPage(Login.class);
+
+ doLogin("bellini", "password");
+
+ TESTER.assertNoErrorMessage();
+ TESTER.assertRenderedPage(Dashboard.class);
+ }
+
+ @Test
+ public void mustChangePassword() {
+ UserTO mustchangepassword = userService.read("mustchangepassword");
+ userService.update(new UserUR.Builder(mustchangepassword.getKey()).
+ mustChangePassword(new BooleanReplacePatchItem.Builder().value(Boolean.TRUE).build()).build());
+
+ TESTER.startPage(Login.class);
+ doLogin("mustchangepassword", "password123");
+
+ TESTER.assertRenderedPage(MustChangePassword.class);
+
+ String changePwdForm = "body:contentWrapper:content:changePasswordPanel:changePassword";
+ TESTER.assertComponent(changePwdForm + ":password", AjaxPasswordFieldPanel.class);
+ TESTER.assertComponent(changePwdForm + ":confirmPassword", AjaxPasswordFieldPanel.class);
+
+ FormTester formTester = TESTER.newFormTester(changePwdForm);
+
+ assertNotNull(formTester);
+ // 1. set new password
+ formTester.setValue(findComponentById(changePwdForm + ":password", "passwordField"), "password124");
+ // 2. confirm password
+ formTester.setValue(findComponentById(changePwdForm + ":confirmPassword", "passwordField"), "password124");
+ // 3. submit form
+ TESTER.executeAjaxEvent(changePwdForm + ":submit", Constants.ON_CLICK);
+
+ TESTER.assertRenderedPage(SelfResult.class);
+
+ TESTER.cleanupFeedbackMessages();
+ TESTER.startPage(Login.class);
+
+ doLogin("mustchangepassword", "password124");
+
+ TESTER.assertNoErrorMessage();
+ TESTER.assertRenderedPage(Dashboard.class);
+ }
+
+ @Test
+ public void selfUpdate() {
+ String username = "selfupdate";
+ String newEmail = "selfupdate@email.com";
+
+ TESTER.startPage(Login.class);
+ doLogin(username, "password123");
+
+ TESTER.assertComponent("body:contentWrapper:content:userProfileInfo:userProfile", WebMarkupContainer.class);
+
+ TESTER.clickLink("body:sidebar:profileLI:profileUL:edituserLI:edituser", false);
+ TESTER.assertRenderedPage(EditUser.class);
+
+ String form = "body:contentWrapper:content:editUserPanel:form";
+ FormTester formTester = TESTER.newFormTester(form);
+ formTester.setValue(
+ "plainAttrsPanelCard:contentPanel:plainSchemas:schemas:4:panel:textField",
+ newEmail);
+
+ // check required fields were correctly set
+ TESTER.assertNoInfoMessage();
+ TESTER.assertNoErrorMessage();
+
+ TESTER.executeAjaxEvent(form + ":submit", Constants.ON_CLICK);
+
+ TESTER.assertRenderedPage(SelfResult.class);
+
+ assertEquals(FlowableDetector.isFlowableEnabledForUserWorkflow(SYNCOPE_SERVICE)
+ ? "active" : "created", userService.read(username).getStatus());
+ assertEquals(newEmail, userService.read(username).getPlainAttr("email").get().getValues().get(0));
+
+ TESTER.cleanupFeedbackMessages();
+ }
+}
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/enduser/EnduserITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/enduser/EnduserITCase.java
deleted file mode 100644
index 3c9545e..0000000
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/enduser/EnduserITCase.java
+++ /dev/null
@@ -1,305 +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.fit.enduser;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-
-import org.apache.commons.lang3.StringUtils;
-import org.apache.syncope.client.enduser.pages.Login;
-import org.apache.syncope.client.enduser.pages.SelfPasswordReset;
-import org.apache.syncope.client.enduser.pages.MustChangePassword;
-import org.apache.syncope.client.lib.SyncopeClient;
-import org.apache.syncope.client.ui.commons.Constants;
-import org.apache.syncope.common.lib.SyncopeConstants;
-import org.apache.syncope.common.lib.request.BooleanReplacePatchItem;
-import org.apache.syncope.common.lib.request.StringReplacePatchItem;
-import org.apache.syncope.common.lib.request.UserUR;
-import org.apache.syncope.common.lib.to.SecurityQuestionTO;
-import org.apache.syncope.common.lib.to.UserTO;
-import org.apache.syncope.common.rest.api.beans.AnyQuery;
-import org.apache.syncope.fit.FlowableDetector;
-import org.apache.wicket.extensions.markup.html.form.palette.component.Choices;
-import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.markup.html.form.Button;
-import org.apache.wicket.markup.html.form.PasswordTextField;
-import org.apache.wicket.markup.html.form.TextField;
-import org.apache.wicket.util.tester.FormTester;
-import org.junit.jupiter.api.Test;
-
-public class EnduserITCase extends AbstractEnduserITCase {
-
- private static final String WIZARD_FORM = "body:wizard:form";
-
- @Test
- public void selfCreate() {
- String username = "testUser";
-
- TESTER.startPage(Login.class);
- TESTER.assertRenderedPage(Login.class);
-
- TESTER.clickLink("self-registration");
-
- TESTER.assertComponent(WIZARD_FORM + ":view:username:textField", TextField.class);
- FormTester formTester = TESTER.newFormTester(WIZARD_FORM);
- assertNotNull(formTester);
- formTester.setValue("view:username:textField", username);
- TESTER.executeAjaxEvent(WIZARD_FORM + ":buttons:next", Constants.ON_CLICK);
-
- // check required field is correctly set
- TESTER.assertNoInfoMessage();
- TESTER.assertNoErrorMessage();
-
- TESTER.assertComponent(WIZARD_FORM + ":view:auxClasses:paletteField:choices", Choices.class);
- TESTER.executeAjaxEvent(WIZARD_FORM + ":buttons:next", Constants.ON_CLICK);
-
- TESTER.assertComponent(WIZARD_FORM + ":view:groupsContainer:groups:form:filter:textField",
- TextField.class);
- TESTER.executeAjaxEvent(WIZARD_FORM + ":buttons:next", Constants.ON_CLICK);
-
- TESTER.assertComponent(findComponentByMarkupId(
- WIZARD_FORM + ":view:plainSchemas:tabs:0:body:content:schemas", "fullname").getPageRelativePath()
- + ":textField",
- TextField.class);
- TESTER.assertComponent(findComponentByMarkupId(
- WIZARD_FORM + ":view:plainSchemas:tabs:0:body:content:schemas", "surname").getPageRelativePath()
- + ":textField",
- TextField.class);
- TESTER.assertComponent(findComponentByMarkupId(
- WIZARD_FORM + ":view:plainSchemas:tabs:0:body:content:schemas", "userId").getPageRelativePath()
- + ":textField",
- TextField.class);
-
- formTester = TESTER.newFormTester(WIZARD_FORM);
- assertNotNull(formTester);
- formTester.setValue(findComponentByMarkupId(WIZARD_FORM
- + ":view:plainSchemas:tabs:0:body:content:schemas",
- "fullname").getPageRelativePath().replace(WIZARD_FORM + ':', StringUtils.EMPTY) + ":textField",
- "User fullname");
- formTester.setValue(findComponentByMarkupId(WIZARD_FORM
- + ":view:plainSchemas:tabs:0:body:content:schemas",
- "surname").getPageRelativePath().replace(WIZARD_FORM + ':', StringUtils.EMPTY) + ":textField",
- "User surname");
- formTester.setValue(
- findComponentByMarkupId(WIZARD_FORM + ":view:plainSchemas:tabs:0:body:content:schemas", "userId").
- getPageRelativePath().replace(WIZARD_FORM + ':', StringUtils.EMPTY) + ":textField",
- "test@email.com");
-
- TESTER.executeAjaxEvent(WIZARD_FORM + ":buttons:next", Constants.ON_CLICK);
-
- // check required fields were correctly set
- TESTER.assertNoInfoMessage();
- TESTER.assertNoErrorMessage();
-
- TESTER.assertComponent(WIZARD_FORM
- + ":view:derSchemas:tabs:0:body:content:schemas:0:panel:textField",
- TextField.class);
-
- TESTER.executeAjaxEvent(WIZARD_FORM + ":buttons:next", Constants.ON_CLICK);
- TESTER.assertComponent(WIZARD_FORM + ":view:virSchemas:tabs:0:body:content:schemas:0:panel:"
- + "multiValueContainer:innerForm:content:field-label",
- Label.class);
-
- TESTER.executeAjaxEvent(WIZARD_FORM + ":buttons:next", Constants.ON_CLICK);
- TESTER.assertComponent(WIZARD_FORM + ":view:resources:paletteField:choices", Choices.class);
-
- TESTER.executeAjaxEvent(WIZARD_FORM + ":buttons:finish", Constants.ON_CLICK);
-
- TESTER.assertRenderedPage(Login.class);
- TESTER.assertComponent("login:username", TextField.class);
-
- assertFalse(userService.search(new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
- fiql(SyncopeClient.getUserSearchConditionBuilder().is("username").equalTo(username).query()).
- build()).getResult().isEmpty());
-
- assertNotNull(userService.read(username));
-
- TESTER.cleanupFeedbackMessages();
-
- // cleanup
- userService.delete(username);
- }
-
- @Test
- public void selfPasswordReset() {
- SecurityQuestionTO question = securityQuestionService.read("887028ea-66fc-41e7-b397-620d7ea6dfbb");
-
- UserTO selfpwdreset = userService.read("selfpwdreset");
- userService.update(new UserUR.Builder(selfpwdreset.getKey()).
- securityQuestion(new StringReplacePatchItem.Builder().value(question.getKey()).build()).
- securityAnswer(new StringReplacePatchItem.Builder().value("ananswer").build()).
- build());
-
- String pwdResetForm = "body:content:selfPwdResetForm";
- TESTER.startPage(Login.class);
- TESTER.assertRenderedPage(Login.class);
-
- TESTER.clickLink("self-pwd-reset");
-
- TESTER.assertRenderedPage(SelfPasswordReset.class);
-
- TESTER.assertComponent(pwdResetForm + ":selfPwdResetPanel:username", TextField.class);
- TESTER.assertComponent(pwdResetForm + ":selfPwdResetPanel:securityQuestion", TextField.class);
-
- FormTester formTester = TESTER.newFormTester(pwdResetForm);
- assertNotNull(formTester);
-
- // 1. set username to selfpwdreset
- formTester.setValue(findComponentById(pwdResetForm + ":selfPwdResetPanel", "username"), "selfpwdreset");
-
- // 2. check that the question has been populated
- TESTER.executeAjaxEvent(pwdResetForm + ":selfPwdResetPanel:username", Constants.ON_BLUR);
- TESTER.assertModelValue(pwdResetForm + ":selfPwdResetPanel:securityQuestion", question.getContent());
-
- // 3. submit form and receive an error
- formTester = TESTER.newFormTester(pwdResetForm);
- assertNotNull(formTester);
- TESTER.executeAjaxEvent(pwdResetForm + ":selfPwdResetPanel:submit", Constants.ON_CLICK);
- TESTER.assertErrorMessages("Invalid security answer");
- TESTER.cleanupFeedbackMessages();
-
- // 3.1 set the correct answer
- formTester = TESTER.newFormTester(pwdResetForm);
- assertNotNull(formTester);
- TESTER.assertComponent(pwdResetForm + ":selfPwdResetPanel:securityAnswer", TextField.class);
- formTester.setValue("selfPwdResetPanel:securityAnswer", "ananswer");
- TESTER.executeAjaxEvent(pwdResetForm + ":selfPwdResetPanel:securityAnswer", Constants.ON_CHANGE);
- TESTER.assertComponent(pwdResetForm + ":selfPwdResetPanel:securityAnswer", TextField.class);
-
- // 4. submit form
- TESTER.assertNoFeedbackMessage(0);
- TESTER.assertNoErrorMessage();
- TESTER.assertComponent(pwdResetForm + ":selfPwdResetPanel:submit", Button.class);
- TESTER.executeAjaxEvent(pwdResetForm + ":selfPwdResetPanel:submit", Constants.ON_CLICK);
- TESTER.assertRenderedPage(Login.class);
- TESTER.assertComponent("login:username", TextField.class);
-
- TESTER.cleanupFeedbackMessages();
- }
-
- @Test
- public void mustChangePassword() {
- UserTO mustchangepassword = userService.read("mustchangepassword");
- userService.update(new UserUR.Builder(mustchangepassword.getKey()).
- mustChangePassword(new BooleanReplacePatchItem.Builder().value(Boolean.TRUE).build()).build());
-
- TESTER.startPage(Login.class);
- doLogin("mustchangepassword", "password123");
-
- TESTER.assertRenderedPage(MustChangePassword.class);
-
- final String changePwdForm = "changePassword";
- TESTER.assertComponent(changePwdForm + ":username", TextField.class);
- TESTER.assertComponent(changePwdForm + ":password:passwordField", PasswordTextField.class);
- TESTER.
- assertComponent(changePwdForm + ":confirmPassword:passwordField", PasswordTextField.class);
- TESTER.assertModelValue(changePwdForm + ":username", "mustchangepassword");
-
- FormTester formTester = TESTER.newFormTester(changePwdForm);
-
- assertNotNull(formTester);
- // 1. set new password
- formTester.setValue(findComponentById(changePwdForm + ":password", "passwordField"), "password124");
- // 2. confirm password
- formTester.setValue(findComponentById(changePwdForm + ":confirmPassword", "passwordField"),
- "password124");
- // 3. submit form
- TESTER.executeAjaxEvent(changePwdForm + ":submit", Constants.ON_CLICK);
-
- TESTER.assertRenderedPage(Login.class);
- TESTER.assertComponent("login:username", TextField.class);
-
- TESTER.cleanupFeedbackMessages();
-
- doLogin("mustchangepassword", "password124");
- TESTER.assertComponent(WIZARD_FORM + ":view:username:textField", TextField.class);
- }
-
- @Test
- public void selfUpdate() {
- String username = "selfupdate";
- String newEmail = "selfupdate@email.com";
-
- TESTER.startPage(Login.class);
- doLogin(username, "password123");
-
- TESTER.assertComponent(WIZARD_FORM + ":view:username:textField", TextField.class);
- TESTER.executeAjaxEvent(WIZARD_FORM + ":buttons:next", Constants.ON_CLICK);
-
- TESTER.assertComponent(WIZARD_FORM + ":view:auxClasses:paletteField:choices", Choices.class);
- TESTER.executeAjaxEvent(WIZARD_FORM + ":buttons:next", Constants.ON_CLICK);
-
- TESTER.assertComponent(WIZARD_FORM + ":view:groupsContainer:groups:form:filter:textField",
- TextField.class);
- TESTER.executeAjaxEvent(WIZARD_FORM + ":buttons:next", Constants.ON_CLICK);
-
- TESTER.assertComponent(findComponentByMarkupId(
- WIZARD_FORM + ":view:plainSchemas:tabs:0:body:content:schemas", "fullname").getPageRelativePath()
- + ":textField",
- TextField.class);
- TESTER.assertComponent(findComponentByMarkupId(
- WIZARD_FORM + ":view:plainSchemas:tabs:0:body:content:schemas", "surname").getPageRelativePath()
- + ":textField",
- TextField.class);
- TESTER.assertComponent(findComponentByMarkupId(
- WIZARD_FORM + ":view:plainSchemas:tabs:0:body:content:schemas", "userId").getPageRelativePath()
- + ":textField",
- TextField.class);
-
- FormTester formTester = TESTER.newFormTester(WIZARD_FORM);
- assertNotNull(formTester);
- TESTER.assertComponent(findComponentByMarkupId(
- WIZARD_FORM + ":view:plainSchemas:tabs:0:body:content:schemas", "email").getPageRelativePath()
- + ":textField",
- TextField.class);
- formTester.setValue(findComponentByMarkupId(WIZARD_FORM
- + ":view:plainSchemas:tabs:0:body:content:schemas",
- "email").getPageRelativePath().replace(WIZARD_FORM + ':', StringUtils.EMPTY) + ":textField",
- newEmail);
-
- TESTER.executeAjaxEvent(WIZARD_FORM + ":buttons:next", Constants.ON_CLICK);
-
- // check required fields were correctly set
- TESTER.assertNoInfoMessage();
- TESTER.assertNoErrorMessage();
-
- TESTER.assertComponent(WIZARD_FORM
- + ":view:derSchemas:tabs:0:body:content:schemas:0:panel:textField",
- TextField.class);
-
- TESTER.executeAjaxEvent(WIZARD_FORM + ":buttons:next", Constants.ON_CLICK);
- TESTER.assertComponent(WIZARD_FORM + ":view:virSchemas:tabs:0:body:content:schemas:0:panel:"
- + "multiValueContainer:innerForm:content:field-label",
- Label.class);
- TESTER.executeAjaxEvent(WIZARD_FORM + ":buttons:next", Constants.ON_CLICK);
- TESTER.assertComponent(WIZARD_FORM + ":view:resources:paletteField:choices", Choices.class);
-
- TESTER.executeAjaxEvent(WIZARD_FORM + ":buttons:finish", Constants.ON_CLICK);
-
- TESTER.assertRenderedPage(Login.class);
- TESTER.assertComponent("login:username", TextField.class);
-
- assertEquals(FlowableDetector.isFlowableEnabledForUserWorkflow(SYNCOPE_SERVICE)
- ? "active" : "created", userService.read(username).getStatus());
- assertEquals(newEmail, userService.read(username).getPlainAttr("email").get().getValues().get(0));
-
- TESTER.cleanupFeedbackMessages();
- }
-}
diff --git a/fit/core-reference/src/test/resources/enduser.properties b/fit/core-reference/src/test/resources/enduser.properties
index 6c48a20..09a8d6e 100644
--- a/fit/core-reference/src/test/resources/enduser.properties
+++ b/fit/core-reference/src/test/resources/enduser.properties
@@ -25,6 +25,15 @@
captcha=false
csrf=false
+# Sidebar
+sidebar=org.apache.syncope.client.enduser.panels.Sidebar
+
+# Page
+page.profile=org.apache.syncope.client.enduser.pages.Dashboard
+page.edituser=org.apache.syncope.client.enduser.pages.EditUser
+page.editchangepassword=org.apache.syncope.client.enduser.pages.EditChangePassword
+page.editsecurityquestion=org.apache.syncope.client.enduser.pages.EditSecurityQuestion
+
security.headers.X-XSS-Protection=1; mode=block
security.headers.Strict-Transport-Security=max-age=31536000; includeSubDomains; preload
security.headers.X-Content-Type-Options=nosniff
diff --git a/fit/enduser-reference/src/main/resources/enduser.properties b/fit/enduser-reference/src/main/resources/enduser.properties
index 1d62418..b4061af 100644
--- a/fit/enduser-reference/src/main/resources/enduser.properties
+++ b/fit/enduser-reference/src/main/resources/enduser.properties
@@ -26,6 +26,15 @@
captcha=true
csrf=true
+# Sidebar
+sidebar=org.apache.syncope.client.enduser.panels.Sidebar
+
+# Page
+page.profile=org.apache.syncope.client.enduser.pages.Dashboard
+page.edituser=org.apache.syncope.client.enduser.pages.EditUser
+page.editchangepassword=org.apache.syncope.client.enduser.pages.EditChangePassword
+page.editsecurityquestion=org.apache.syncope.client.enduser.pages.EditSecurityQuestion
+
security.headers.X-XSS-Protection=1; mode=block
security.headers.Strict-Transport-Security=max-age=31536000; includeSubDomains; preload
security.headers.X-Content-Type-Options=nosniff