This is an automated email from the ASF dual-hosted git repository. ilgrosso pushed a commit to branch 4_0_X in repository https://gitbox.apache.org/repos/asf/syncope.git
commit 31a422f0762a0bfa5b5f35d533630c9fb61bcd14 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 b5e5654420..8906b8e431 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); formTester = TESTER.newFormTester( 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 a8848445a3..190c18a6b2 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 @@ -522,7 +522,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 @@ -568,7 +568,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",
