This is an automated email from the ASF dual-hosted git repository.
ilgrosso pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/syncope.git
The following commit(s) were added to refs/heads/master by this push:
new e682ef7bdb [SYNCOPE-1958] Check account and passord policy compliance
before save
e682ef7bdb is described below
commit e682ef7bdbe143c76629799a20f634ecaa85a583
Author: Francesco Chicchiriccò <[email protected]>
AuthorDate: Thu Apr 2 15:31:13 2026 +0200
[SYNCOPE-1958] Check account and passord policy compliance before save
---
.../ui/commons/rest/UserComplianceRestClient.java | 26 +++++++++
.../client/ui/commons/wizards/AjaxWizard.java | 6 +-
.../ui/commons/wizards/any/PasswordPanel.java | 65 ++++++++++++++--------
.../client/console/rest/UserRestClient.java | 11 +++-
.../client/console/status/ChangePasswordModal.java | 2 +-
.../client/console/wizards/any/UserDetails.java | 43 ++++++++++++--
.../client/console/wizards/any/UserDetails.html | 8 ++-
.../enduser/pages/SelfConfirmPasswordReset.java | 9 ++-
.../client/enduser/panels/any/UserDetails.java | 55 ++++++++++++++----
.../client/enduser/rest/UserSelfRestClient.java | 10 +++-
.../client/enduser/panels/any/UserDetails.html | 8 ++-
.../apache/syncope/fit/console/PoliciesITCase.java | 2 +-
.../apache/syncope/fit/console/RealmsITCase.java | 6 +-
.../apache/syncope/fit/console/UsersITCase.java | 8 +--
.../syncope/fit/enduser/AnonymousITCase.java | 2 +-
15 files changed, 199 insertions(+), 62 deletions(-)
diff --git
a/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/rest/UserComplianceRestClient.java
b/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/rest/UserComplianceRestClient.java
new file mode 100644
index 0000000000..e541717cb1
--- /dev/null
+++
b/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/rest/UserComplianceRestClient.java
@@ -0,0 +1,26 @@
+/*
+ * 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.rest;
+
+import org.apache.syncope.common.rest.api.beans.ComplianceQuery;
+
+public interface UserComplianceRestClient extends RestClient {
+
+ void compliance(ComplianceQuery query);
+}
diff --git
a/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/wizards/AjaxWizard.java
b/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/wizards/AjaxWizard.java
index d47a412536..e79e5d435c 100644
---
a/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/wizards/AjaxWizard.java
+++
b/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/wizards/AjaxWizard.java
@@ -199,11 +199,11 @@ public abstract class AjaxWizard<T extends Serializable>
extends Wizard
public final void onFinish() {
AjaxRequestTarget target =
RequestCycle.get().find(AjaxRequestTarget.class).orElse(null);
try {
- final Serializable res = onApply(target);
+ Serializable applied = onApply(target);
if (eventSink == null) {
- send(this, Broadcast.BUBBLE, new NewItemFinishEvent<>(item,
target).setResult(res));
+ send(this, Broadcast.BUBBLE, new NewItemFinishEvent<>(item,
target).setResult(applied));
} else {
- send(eventSink, Broadcast.EXACT, new
NewItemFinishEvent<>(item, target).setResult(res));
+ send(eventSink, Broadcast.EXACT, new
NewItemFinishEvent<>(item, target).setResult(applied));
}
} catch (TimeoutException te) {
LOG.warn("Operation took too long", te);
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 214c64ff92..8c99e37a9a 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
@@ -22,9 +22,14 @@ import
de.agilecoders.wicket.extensions.markup.html.bootstrap.form.password.stre
import org.apache.syncope.client.ui.commons.markup.html.form.AjaxCheckBoxPanel;
import
org.apache.syncope.client.ui.commons.markup.html.form.AjaxPasswordFieldPanel;
import
org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
+import
org.apache.syncope.client.ui.commons.markup.html.form.SyncopePasswordStrengthConfig;
+import org.apache.syncope.client.ui.commons.rest.UserComplianceRestClient;
+import org.apache.syncope.common.rest.api.beans.ComplianceQuery;
import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.markup.html.form.FormComponent;
import org.apache.wicket.markup.html.form.PasswordTextField;
import
org.apache.wicket.markup.html.form.validation.EqualPasswordInputValidator;
+import org.apache.wicket.markup.html.form.validation.IFormValidator;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.PropertyModel;
@@ -38,17 +43,8 @@ public class PasswordPanel extends Panel {
final String id,
final UserWrapper wrapper,
final Boolean storePasswordInSyncope,
- final boolean templateMode) {
-
- this(id, wrapper, templateMode, storePasswordInSyncope, null);
- }
-
- public PasswordPanel(
- final String id,
- final UserWrapper wrapper,
final boolean templateMode,
- final Boolean storePasswordInSyncope,
- final PasswordStrengthBehavior passwordStrengthBehavior) {
+ final UserComplianceRestClient restClient) {
super(id);
setOutputMarkupId(true);
@@ -56,14 +52,14 @@ public class PasswordPanel extends Panel {
Form<?> form = new Form<>("passwordInnerForm");
add(form);
- AjaxPasswordFieldPanel confirmPasswordField = new
AjaxPasswordFieldPanel(
+ AjaxPasswordFieldPanel confirmPassword = new AjaxPasswordFieldPanel(
"confirmPassword", "confirmPassword", Model.of(), false);
- ((PasswordTextField)
confirmPasswordField.getField()).setResetPassword(false);
-
form.add(confirmPasswordField.setPlaceholder("confirmPassword").setMarkupId("confirmPassword"));
+ ((PasswordTextField)
confirmPassword.getField()).setResetPassword(false);
+
form.add(confirmPassword.setPlaceholder("confirmPassword").setMarkupId("confirmPassword"));
if (templateMode) {
- confirmPasswordField.setEnabled(false);
- confirmPasswordField.setVisible(false);
+ confirmPassword.setEnabled(false);
+ confirmPassword.setVisible(false);
AjaxTextFieldPanel passwordField = new AjaxTextFieldPanel(
"password", "password", new
PropertyModel<>(wrapper.getInnerObject(), "password"), false);
@@ -73,18 +69,41 @@ public class PasswordPanel extends Panel {
form.add(passwordField);
passwordField.enableJexlHelp();
} else {
- AjaxPasswordFieldPanel passwordField = new AjaxPasswordFieldPanel(
+ AjaxPasswordFieldPanel password = new AjaxPasswordFieldPanel(
"password",
"password",
new PropertyModel<>(wrapper.getInnerObject(), "password"),
false,
- passwordStrengthBehavior);
- passwordField.setRequired(true);
- passwordField.setMarkupId("password");
- passwordField.setPlaceholder("password");
- ((PasswordTextField)
passwordField.getField()).setResetPassword(false);
- form.add(passwordField);
- form.add(new EqualPasswordInputValidator(passwordField.getField(),
confirmPasswordField.getField()));
+ new PasswordStrengthBehavior(new
SyncopePasswordStrengthConfig()));
+ password.setRequired(true);
+ password.setMarkupId("password");
+ password.setPlaceholder("password");
+ ((PasswordTextField) password.getField()).setResetPassword(false);
+ form.add(password);
+ form.add(new EqualPasswordInputValidator(password.getField(),
confirmPassword.getField()));
+ form.add(new IFormValidator() {
+
+ private static final long serialVersionUID =
-73522462874258637L;
+
+ @Override
+ public FormComponent<?>[] getDependentFormComponents() {
+ return null;
+ }
+
+ @Override
+ public void validate(final Form<?> form) {
+ ComplianceQuery quey = new ComplianceQuery.Builder().
+ realm(wrapper.getInnerObject().getRealm()).
+ password(password.getField().getInput()).
+ resources(wrapper.getInnerObject().getResources()).
+ build();
+ try {
+ restClient.compliance(quey);
+ } catch (Exception e) {
+ password.getField().error(e.getMessage());
+ }
+ }
+ });
}
AjaxCheckBoxPanel storePasswordInSyncopePanel = new
AjaxCheckBoxPanel("storePasswordInSyncope",
diff --git
a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/UserRestClient.java
b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/UserRestClient.java
index 224bbb8065..cc3cae9679 100644
---
a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/UserRestClient.java
+++
b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/UserRestClient.java
@@ -22,7 +22,9 @@ import jakarta.ws.rs.core.GenericType;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import org.apache.syncope.client.console.SyncopeConsoleSession;
import org.apache.syncope.client.ui.commons.Constants;
+import org.apache.syncope.client.ui.commons.rest.UserComplianceRestClient;
import org.apache.syncope.client.ui.commons.status.Status;
import org.apache.syncope.client.ui.commons.status.StatusBean;
import org.apache.syncope.client.ui.commons.status.StatusUtils;
@@ -35,14 +37,16 @@ import org.apache.syncope.common.lib.to.UserTO;
import org.apache.syncope.common.lib.types.ExecStatus;
import org.apache.syncope.common.lib.types.StatusRType;
import org.apache.syncope.common.rest.api.beans.AnyQuery;
+import org.apache.syncope.common.rest.api.beans.ComplianceQuery;
import org.apache.syncope.common.rest.api.service.AnyService;
+import org.apache.syncope.common.rest.api.service.UserSelfService;
import org.apache.syncope.common.rest.api.service.UserService;
import org.apache.wicket.extensions.markup.html.repeater.util.SortParam;
/**
* Console client for invoking rest users services.
*/
-public class UserRestClient extends AbstractAnyRestClient<UserTO> {
+public class UserRestClient extends AbstractAnyRestClient<UserTO> implements
UserComplianceRestClient {
private static final long serialVersionUID = -1575748964398293968L;
@@ -51,6 +55,11 @@ public class UserRestClient extends
AbstractAnyRestClient<UserTO> {
return UserService.class;
}
+ @Override
+ public void compliance(final ComplianceQuery query) {
+
SyncopeConsoleSession.get().getAnonymousService(UserSelfService.class).compliance(query);
+ }
+
public ProvisioningResult<UserTO> create(final UserCR createReq) {
return getService(UserService.class).create(createReq).readEntity(new
GenericType<>() {
});
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 bc77114bb6..02696dce1a 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
@@ -60,7 +60,7 @@ public class ChangePasswordModal extends
AbstractModalPanel<AnyWrapper<UserTO>>
super(baseModal, pageRefer);
this.wrapper = wrapper;
- PasswordPanel passwordPanel = new PasswordPanel("passwordPanel",
wrapper, false, false);
+ PasswordPanel passwordPanel = new PasswordPanel("passwordPanel",
wrapper, false, false, userRestClient);
passwordPanel.setOutputMarkupId(true);
add(passwordPanel);
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 ccb2003c32..a82f23c814 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
@@ -20,6 +20,7 @@ package org.apache.syncope.client.console.wizards.any;
import java.util.List;
import org.apache.commons.lang3.Strings;
+import org.apache.syncope.client.console.rest.UserRestClient;
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.AjaxCheckBoxPanel;
@@ -28,6 +29,7 @@ import
org.apache.syncope.client.ui.commons.wicket.markup.html.bootstrap.tabs.Ac
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.UserTO;
+import org.apache.syncope.common.rest.api.beans.ComplianceQuery;
import org.apache.wicket.Component;
import org.apache.wicket.PageReference;
import org.apache.wicket.ajax.AjaxRequestTarget;
@@ -35,15 +37,22 @@ 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.markup.html.basic.Label;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.markup.html.form.FormComponent;
+import org.apache.wicket.markup.html.form.validation.IFormValidator;
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.spring.injection.annot.SpringBean;
public class UserDetails extends Details<UserTO> {
private static final long serialVersionUID = 6592027822510220463L;
+ @SpringBean
+ protected UserRestClient restClient;
+
public UserDetails(
final UserWrapper wrapper,
final boolean templateMode,
@@ -58,9 +67,13 @@ public class UserDetails extends Details<UserTO> {
// ------------------------
// Username
// ------------------------
+ Form<?> form = new Form<>("usernameInnerForm");
+ add(form);
+
AjaxTextFieldPanel username = new AjaxTextFieldPanel(
Constants.USERNAME_FIELD_NAME, Constants.USERNAME_FIELD_NAME,
new PropertyModel<>(userTO, Constants.USERNAME_FIELD_NAME),
false);
+ form.add(username);
if (wrapper.getPreviousUserTO() != null && Strings.CS.compare(
wrapper.getPreviousUserTO().getUsername(),
wrapper.getInnerObject().getUsername()) != 0) {
@@ -72,8 +85,31 @@ public class UserDetails extends Details<UserTO> {
username.enableJexlHelp();
} else {
username.addRequiredLabel();
+
+ form.add(new IFormValidator() {
+
+ private static final long serialVersionUID =
-73522462874258637L;
+
+ @Override
+ public FormComponent<?>[] getDependentFormComponents() {
+ return null;
+ }
+
+ @Override
+ public void validate(final Form<?> form) {
+ ComplianceQuery quey = new ComplianceQuery.Builder().
+ realm(wrapper.getInnerObject().getRealm()).
+ username(username.getField().getInput()).
+ resources(wrapper.getInnerObject().getResources()).
+ build();
+ try {
+ restClient.compliance(quey);
+ } catch (Exception e) {
+ username.getField().error(e.getMessage());
+ }
+ }
+ });
}
- add(username);
// ------------------------
// ------------------------
@@ -121,7 +157,6 @@ public class UserDetails extends Details<UserTO> {
}.setBody(new ResourceModel("password.change", "Change
password ..."));
}
};
-
accordion.setOutputMarkupId(true);
accordion.setVisible(showPasswordManagement);
add(accordion);
@@ -133,7 +168,7 @@ public class UserDetails extends Details<UserTO> {
return new UserInformationPanel(id, anyTO);
}
- public static class EditUserPasswordPanel extends Panel {
+ protected class EditUserPasswordPanel extends Panel {
private static final long serialVersionUID = -8198836979773590078L;
@@ -141,7 +176,7 @@ public class UserDetails extends Details<UserTO> {
super(id);
setOutputMarkupId(true);
add(new Label("warning", new
ResourceModel("password.change.warning")));
- add(new PasswordPanel("passwordPanel", wrapper, false,
templateMode));
+ add(new PasswordPanel("passwordPanel", wrapper, false,
templateMode, restClient));
}
}
}
diff --git
a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wizards/any/UserDetails.html
b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wizards/any/UserDetails.html
index e7fa169f79..58b2e693fb 100644
---
a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wizards/any/UserDetails.html
+++
b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wizards/any/UserDetails.html
@@ -18,9 +18,11 @@ under the License.
-->
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:wicket="http://wicket.apache.org">
<wicket:extend>
- <div class="form-group mb-3">
- <span wicket:id="username"/>
- </div>
+ <form wicket:id="usernameInnerForm">
+ <div class="form-group mb-3">
+ <span wicket:id="username"/>
+ </div>
+ </form>
<div class="form-group mb-3">
<span wicket:id="mustChangePassword"/>
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 e3663ee547..3f30f4ae5a 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,11 +18,10 @@
*/
package org.apache.syncope.client.enduser.pages;
-import
de.agilecoders.wicket.extensions.markup.html.bootstrap.form.password.strength.PasswordStrengthBehavior;
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.SyncopePasswordStrengthConfig;
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;
@@ -37,6 +36,7 @@ import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.StatelessForm;
import org.apache.wicket.model.Model;
import org.apache.wicket.request.mapper.parameter.PageParameters;
+import org.apache.wicket.spring.injection.annot.SpringBean;
import org.wicketstuff.kendo.ui.widget.notification.Notification;
public class SelfConfirmPasswordReset extends BasePage {
@@ -45,6 +45,9 @@ public class SelfConfirmPasswordReset extends BasePage {
private static final String CONFIRM_PASSWORD_RESET =
"confirmPasswordReset";
+ @SpringBean
+ protected UserSelfRestClient restClient;
+
public SelfConfirmPasswordReset(final PageParameters parameters) {
super(parameters, CONFIRM_PASSWORD_RESET);
@@ -74,7 +77,7 @@ public class SelfConfirmPasswordReset extends BasePage {
new UserWrapper(fakeUserTO),
false,
false,
- new PasswordStrengthBehavior(new
SyncopePasswordStrengthConfig()));
+ restClient);
passwordPanel.setOutputMarkupId(true);
form.add(new CardPanel.Builder<PasswordPanel>()
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
index aa0bbabafc..730d3ea728 100644
---
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
@@ -18,30 +18,35 @@
*/
package org.apache.syncope.client.enduser.panels.any;
-import
de.agilecoders.wicket.extensions.markup.html.bootstrap.form.password.strength.PasswordStrengthBehavior;
import java.util.List;
import java.util.Optional;
import org.apache.commons.lang3.Strings;
+import org.apache.syncope.client.enduser.rest.UserSelfRestClient;
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.markup.html.form.SyncopePasswordStrengthConfig;
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.SyncopeConstants;
import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.common.rest.api.beans.ComplianceQuery;
import org.apache.wicket.PageReference;
import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.markup.html.form.FormComponent;
+import org.apache.wicket.markup.html.form.validation.IFormValidator;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.model.ResourceModel;
+import org.apache.wicket.spring.injection.annot.SpringBean;
public class UserDetails extends Details<UserTO> {
private static final long serialVersionUID = 6592027822510220463L;
- protected final AjaxTextFieldPanel username;
+ @SpringBean
+ protected UserSelfRestClient restClient;
protected final UserTO userTO;
@@ -49,18 +54,46 @@ public class UserDetails extends Details<UserTO> {
super(id, pageRef);
userTO = wrapper.getInnerObject();
+
// ------------------------
// Username
// ------------------------
- username = new AjaxTextFieldPanel("username", "username", new
PropertyModel<>(userTO, "username"), false);
+ Form<?> form = new Form<>("usernameInnerForm");
+ add(form);
+
+ AjaxTextFieldPanel username = new AjaxTextFieldPanel(
+ "username", "username", new PropertyModel<>(userTO,
"username"), false);
+
+ if (wrapper.getPreviousUserTO() != null && Strings.CS.compare(
+ wrapper.getPreviousUserTO().getUsername(),
wrapper.getInnerObject().getUsername()) != 0) {
- if (wrapper.getPreviousUserTO() != null && Strings.CS.
- compare(wrapper.getPreviousUserTO().getUsername(),
wrapper.getInnerObject().getUsername()) != 0) {
username.showExternAction(new LabelInfo("externalAction",
wrapper.getPreviousUserTO().getUsername()));
}
- username.addRequiredLabel();
- add(username);
+ form.add(username.addRequiredLabel());
+ form.add(new IFormValidator() {
+
+ private static final long serialVersionUID = -73522462874258637L;
+
+ @Override
+ public FormComponent<?>[] getDependentFormComponents() {
+ return null;
+ }
+
+ @Override
+ public void validate(final Form<?> form) {
+ ComplianceQuery quey = new ComplianceQuery.Builder().
+ realm(wrapper.getInnerObject().getRealm()).
+ username(username.getField().getInput()).
+ resources(wrapper.getInnerObject().getResources()).
+ build();
+ try {
+ restClient.compliance(quey);
+ } catch (Exception e) {
+ username.getField().error(e.getMessage());
+ }
+ }
+ });
// ------------------------
// ------------------------
@@ -78,7 +111,7 @@ public class UserDetails extends Details<UserTO> {
return destinationRealm;
}
- protected static class EditUserPasswordPanel extends Panel {
+ protected class EditUserPasswordPanel extends Panel {
private static final long serialVersionUID = -8198836979773590078L;
@@ -89,9 +122,9 @@ public class UserDetails extends Details<UserTO> {
add(new PasswordPanel(
"passwordPanel",
wrapper,
- false,
wrapper.getInnerObject().getKey() == null,
- new PasswordStrengthBehavior(new
SyncopePasswordStrengthConfig())));
+ false,
+ restClient));
}
}
}
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 93e114b10e..8c90bffde3 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
@@ -19,14 +19,17 @@
package org.apache.syncope.client.enduser.rest;
import jakarta.ws.rs.core.GenericType;
+import org.apache.syncope.client.enduser.SyncopeEnduserSession;
+import org.apache.syncope.client.ui.commons.rest.UserComplianceRestClient;
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.syncope.common.rest.api.beans.ComplianceQuery;
import org.apache.syncope.common.rest.api.service.UserSelfService;
-public class UserSelfRestClient extends BaseRestClient {
+public class UserSelfRestClient extends BaseRestClient implements
UserComplianceRestClient {
private static final long serialVersionUID = -1575748964398293968L;
@@ -38,6 +41,11 @@ public class UserSelfRestClient extends BaseRestClient {
getService(UserSelfService.class).requestPasswordReset(username,
securityAnswer);
}
+ @Override
+ public void compliance(final ComplianceQuery query) {
+
SyncopeEnduserSession.get().getAnonymousService(UserSelfService.class).compliance(query);
+ }
+
public ProvisioningResult<UserTO> create(final UserCR createReq) {
return
getService(UserSelfService.class).create(createReq).readEntity(new
GenericType<>() {
});
diff --git
a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/UserDetails.html
b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/UserDetails.html
index 85d266ef57..18587c0c2a 100644
---
a/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/UserDetails.html
+++
b/client/idrepo/enduser/src/main/resources/org/apache/syncope/client/enduser/panels/any/UserDetails.html
@@ -23,9 +23,11 @@ under the License.
<div class="form-group mb-3">
<span wicket:id="destinationRealm">[DESTINATION REALM]</span>
</div>
- <div class="form-group mb-3">
- <span wicket:id="username"/>
- </div>
+ <form wicket:id="usernameInnerForm">
+ <div class="form-group mb-3">
+ <span wicket:id="username"/>
+ </div>
+ </form>
<wicket:child/>
</div>
</wicket:panel>
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 ac0c5ad673..337423b3e1 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
@@ -785,7 +785,7 @@ public class PoliciesITCase extends AbstractConsoleITCase {
TESTER.assertComponent(
"body:content:body:container:content:tabbedPanel:panel:searchResult:"
- +
"outerObjectsRepeater:0:outer:form:content:form:view:username:textField",
+ +
"outerObjectsRepeater:0:outer:form:content:form:view:usernameInnerForm:username:textField",
TextField.class);
for (int i = 0; i < 4; i++) {
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 478923c43a..8193c34b9d 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
@@ -129,7 +129,7 @@ public class RealmsITCase extends AbstractConsoleITCase {
TESTER.assertComponent("body:templateModal", Modal.class);
formTester =
TESTER.newFormTester("body:templateModal:form:content:form");
- formTester.setValue("view:username:textField", "'k' + firstname");
+ formTester.setValue("view:usernameInnerForm:username:textField", "'k'
+ firstname");
formTester.submit("buttons:finish");
assertSuccessMessage();
@@ -147,11 +147,11 @@ public class RealmsITCase extends AbstractConsoleITCase {
TESTER.assertComponent("body:templateModal", Modal.class);
-
TESTER.assertModelValue("body:templateModal:form:content:form:view:username:textField",
+
TESTER.assertModelValue("body:templateModal:form:content:form:view:usernameInnerForm:username:textField",
"'k' + firstname");
formTester =
TESTER.newFormTester("body:templateModal:form:content:form");
- formTester.setValue("view:username:textField", "");
+ formTester.setValue("view:usernameInnerForm:username:textField", "");
formTester.submit("buttons:finish");
assertSuccessMessage();
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 8223b93901..e57a3b5edf 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
@@ -100,7 +100,7 @@ public class UsersITCase extends AbstractConsoleITCase {
+ "actions:actions:actionRepeater:10:action:action");
TESTER.assertComponent(TAB_PANEL
- +
"outerObjectsRepeater:0:outer:form:content:form:view:username:textField",
+ +
"outerObjectsRepeater:0:outer:form:content:form:view:usernameInnerForm:username:textField",
TextField.class);
FormTester formTester = TESTER.newFormTester(TAB_PANEL
@@ -125,7 +125,7 @@ public class UsersITCase extends AbstractConsoleITCase {
+ "actions:actions:actionRepeater:0:action:action");
TESTER.assertComponent(TAB_PANEL
- +
"outerObjectsRepeater:0:outer:form:content:form:view:username:textField",
+ +
"outerObjectsRepeater:0:outer:form:content:form:view:usernameInnerForm:username:textField",
TextField.class);
FormTester formTester = TESTER.newFormTester(TAB_PANEL
@@ -541,7 +541,7 @@ public class UsersITCase extends AbstractConsoleITCase {
+ "actions:actions:actionRepeater:0:action:action");
TESTER.assertComponent(TAB_PANEL
- +
"outerObjectsRepeater:0:outer:form:content:form:view:username:textField",
+ +
"outerObjectsRepeater:0:outer:form:content:form:view:usernameInnerForm:username:textField",
TextField.class);
FormTester formTester = TESTER.newFormTester(TAB_PANEL
@@ -587,7 +587,7 @@ public class UsersITCase extends AbstractConsoleITCase {
+ "actions:actions:actionRepeater:0:action:action");
TESTER.assertComponent(TAB_PANEL
- +
"outerObjectsRepeater:0:outer:form:content:form:view:username:textField",
+ +
"outerObjectsRepeater:0:outer:form:content:form:view:usernameInnerForm:username:textField",
TextField.class);
formTester = TESTER.newFormTester(TAB_PANEL +
"outerObjectsRepeater:0:outer:form:content:form");
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
index ba881a1469..b190552831 100644
---
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
@@ -51,7 +51,7 @@ public class AnonymousITCase extends AbstractEnduserITCase {
String form = "body:contentWrapper:content:selfRegistrationPanel:form";
FormTester formTester = TESTER.newFormTester(form);
-
formTester.setValue("userDetailsPanelCard:contentPanel:username:textField",
username);
+
formTester.setValue("userDetailsPanelCard:contentPanel:usernameInnerForm:username:textField",
username);
formTester.setValue(
"userDetailsPanelCard:contentPanel:password:passwordPanel:passwordInnerForm:password:passwordField",