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
The following commit(s) were added to refs/heads/4_0_X by this push:
new c1c3c807ff [SYNCOPE-1960] Remove related attributes when removing aux
classes
c1c3c807ff is described below
commit c1c3c807ff11fbb6c9578902379c1cbe602b307f
Author: Francesco Chicchiriccò <[email protected]>
AuthorDate: Wed Apr 8 09:52:47 2026 +0200
[SYNCOPE-1960] Remove related attributes when removing aux classes
---
.../client/console/wizards/any/Resources.java | 49 ++++++++++++-
.../wizards/any/AbstractAnyWizardBuilder.java | 56 ---------------
.../ui/commons/wizards/any/AbstractAuxClasses.java | 72 -------------------
.../ui/commons/wizards/any/AbstractGroups.java | 81 ----------------------
.../ui/commons/wizards/any/AbstractResources.java | 73 -------------------
.../syncope/client/console/panels/AnyPanel.java | 3 +-
.../wizards/any/AnyObjectWizardBuilder.java | 7 +-
.../console/wizards/any/AnyWizardBuilder.java | 32 ++-------
.../console/wizards/any/ConsoleAuxClasses.java | 44 ++++++++++--
.../console/wizards/any/GroupWizardBuilder.java | 7 +-
.../syncope/client/console/wizards/any/Groups.java | 47 +++++++++++--
.../core/provisioning/java/data/AnyDataBinder.java | 35 +++++-----
.../java/data/AnyObjectDataBinderImpl.java | 2 +-
.../java/data/GroupDataBinderImpl.java | 2 +-
.../provisioning/java/data/UserDataBinderImpl.java | 2 +-
.../apache/syncope/fit/core/AnyObjectITCase.java | 34 +++++++++
pom.xml | 2 +-
17 files changed, 195 insertions(+), 353 deletions(-)
diff --git
a/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/any/Resources.java
b/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/any/Resources.java
index db2aeec635..029b76b97a 100644
---
a/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/any/Resources.java
+++
b/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/any/Resources.java
@@ -18,20 +18,63 @@
*/
package org.apache.syncope.client.console.wizards.any;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.commons.lang3.StringUtils;
import org.apache.syncope.client.console.SyncopeWebApplication;
-import org.apache.syncope.client.ui.commons.wizards.any.AbstractResources;
+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.lib.types.IdMEntitlement;
import
org.apache.wicket.authroles.authorization.strategies.role.metadata.ActionPermissions;
import
org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
+import org.apache.wicket.extensions.wizard.WizardModel;
+import org.apache.wicket.extensions.wizard.WizardStep;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.model.PropertyModel;
+import org.apache.wicket.model.util.ListModel;
-public class Resources extends AbstractResources {
+public class Resources extends WizardStep implements WizardModel.ICondition {
private static final long serialVersionUID = 702900610508752856L;
+ protected final AnyTO anyTO;
+
+ protected final ListModel<String> available;
+
public <T extends AnyTO> Resources(final AnyWrapper<T> modelObject) {
- super(modelObject);
+ anyTO = modelObject.getInnerObject();
+
+ if (modelObject instanceof UserWrapper userWrapper
+ && userWrapper.getPreviousUserTO() != null
+ && !modelObject.getInnerObject().getResources().equals(
+ userWrapper.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<>(anyTO, "resources") {
+
+ private static final long serialVersionUID = 3799387950428254072L;
+
+ @Override
+ public List<String> getObject() {
+ return new ArrayList<>(anyTO.getResources());
+ }
+
+ @Override
+ public void setObject(final List<String> object) {
+ anyTO.getResources().clear();
+ anyTO.getResources().addAll(object);
+ }
+ }, available).hideLabel().setOutputMarkupId(true));
// -----------------------------------------------------------------
// Pre-Authorizations
diff --git
a/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/wizards/any/AbstractAnyWizardBuilder.java
b/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/wizards/any/AbstractAnyWizardBuilder.java
deleted file mode 100644
index 01d5dd70ef..0000000000
---
a/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/wizards/any/AbstractAnyWizardBuilder.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.ui.commons.wizards.any;
-
-import org.apache.syncope.client.ui.commons.wizards.AjaxWizardBuilder;
-import org.apache.syncope.common.lib.to.AnyTO;
-import org.apache.syncope.common.lib.to.GroupableRelatableTO;
-import org.apache.wicket.PageReference;
-
-public abstract class AbstractAnyWizardBuilder<A extends AnyTO> extends
AjaxWizardBuilder<AnyWrapper<A>> {
-
- private static final long serialVersionUID = -2480279868319546243L;
-
- public AbstractAnyWizardBuilder(final AnyWrapper<A> defaultItem, final
PageReference pageRef) {
- super(defaultItem, pageRef);
- }
-
- protected void fixPlainAttrs(final AnyTO updated, final AnyTO original) {
- // re-add to the updated object any missing plain attribute (compared
to original): this to cope with
- // form layout, which might have not included some plain attributes
- original.getPlainAttrs().stream().
- filter(attr ->
updated.getPlainAttr(attr.getSchema()).isPresent()).
- forEach(attr -> updated.getPlainAttrs().add(attr));
- if (updated instanceof GroupableRelatableTO updatedTO && original
instanceof GroupableRelatableTO originalTO) {
- originalTO.getMemberships().
- forEach(oMemb ->
updatedTO.getMembership(oMemb.getGroupKey()).
- ifPresent(uMemb -> oMemb.getPlainAttrs().stream().
- filter(attr ->
uMemb.getPlainAttr(attr.getSchema()).isPresent()).
- forEach(attr -> uMemb.getPlainAttrs().add(attr))));
- }
-
- // remove from the updated object any plain attribute without values,
thus triggering for removal in
- // the generated patch
- updated.getPlainAttrs().removeIf(attr -> attr.getValues().isEmpty());
- if (updated instanceof GroupableRelatableTO updatedTO) {
- updatedTO.getMemberships().
- forEach(memb -> memb.getPlainAttrs().removeIf(attr ->
attr.getValues().isEmpty()));
- }
- }
-}
diff --git
a/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/wizards/any/AbstractAuxClasses.java
b/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/wizards/any/AbstractAuxClasses.java
deleted file mode 100644
index 4df345008f..0000000000
---
a/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/wizards/any/AbstractAuxClasses.java
+++ /dev/null
@@ -1,72 +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.ui.commons.wizards.any;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import org.apache.commons.collections4.ListUtils;
-import org.apache.commons.lang3.StringUtils;
-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.common.lib.to.AnyTO;
-import org.apache.syncope.common.lib.to.AnyTypeClassTO;
-import org.apache.wicket.extensions.wizard.WizardStep;
-import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.model.PropertyModel;
-import org.apache.wicket.model.util.ListModel;
-
-public abstract class AbstractAuxClasses extends WizardStep {
-
- private static final long serialVersionUID = 552437609667518888L;
-
- public <T extends AnyTO> AbstractAuxClasses(final AnyWrapper<T>
modelObject, final List<String> anyTypeClasses) {
- super();
- setOutputMarkupId(true);
-
- List<AnyTypeClassTO> allAnyTypeClasses = listAnyTypecClasses();
-
- List<String> choices = new ArrayList<>();
- for (AnyTypeClassTO aux : allAnyTypeClasses) {
- if (!anyTypeClasses.contains(aux.getKey())) {
- choices.add(aux.getKey());
- }
- }
- Collections.sort(choices);
- add(new
AjaxPalettePanel.Builder<String>().setAllowOrder(true).build("auxClasses",
- new PropertyModel<>(modelObject.getInnerObject(),
"auxClasses"),
- new ListModel<>(choices)).hideLabel().setOutputMarkupId(true));
-
- // ------------------
- // insert changed label if needed
- // ------------------
- if (modelObject instanceof UserWrapper
- && UserWrapper.class.cast(modelObject).getPreviousUserTO() !=
null
- && !ListUtils.isEqualList(
- modelObject.getInnerObject().getAuxClasses(),
-
UserWrapper.class.cast(modelObject).getPreviousUserTO().getAuxClasses())) {
- add(new LabelInfo("changed", StringUtils.EMPTY));
- } else {
- add(new Label("changed", StringUtils.EMPTY));
- }
- // ------------------
- }
-
- protected abstract List<AnyTypeClassTO> listAnyTypecClasses();
-}
diff --git
a/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/wizards/any/AbstractGroups.java
b/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/wizards/any/AbstractGroups.java
deleted file mode 100644
index 45c9fdf27d..0000000000
---
a/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/wizards/any/AbstractGroups.java
+++ /dev/null
@@ -1,81 +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.ui.commons.wizards.any;
-
-import org.apache.commons.collections4.ListUtils;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.syncope.client.ui.commons.ajax.markup.html.LabelInfo;
-import org.apache.syncope.common.lib.to.AnyTO;
-import org.apache.wicket.extensions.wizard.WizardModel.ICondition;
-import org.apache.wicket.extensions.wizard.WizardStep;
-import org.apache.wicket.markup.html.WebMarkupContainer;
-import org.apache.wicket.markup.html.basic.Label;
-
-public abstract class AbstractGroups extends WizardStep implements ICondition {
-
- private static final long serialVersionUID = 552437609667518888L;
-
- protected static final int MAX_GROUP_LIST_CARDINALITY = 30;
-
- protected final AnyTO anyTO;
-
- protected WebMarkupContainer dyngroupsContainer;
-
- protected WebMarkupContainer dynrealmsContainer;
-
- protected WebMarkupContainer groupsContainer;
-
- public <T extends AnyTO> AbstractGroups(final AnyWrapper<T> modelObject) {
- super();
- 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 final UserWrapper uw
- && uw.getPreviousUserTO() != null
- && !ListUtils.isEqualList(
- uw.getInnerObject().getMemberships(),
- uw.getPreviousUserTO().getMemberships())) {
-
- groupsContainer.add(new LabelInfo("changed", StringUtils.EMPTY));
- } else {
- groupsContainer.add(new Label("changed", StringUtils.EMPTY));
- }
- // ------------------
- }
-
- protected abstract void addGroupsPanel();
-
- protected abstract void addDynamicRealmsContainer();
-
- protected abstract void addDynamicGroupsContainer();
-
- @Override
- public boolean evaluate() {
- return true;
- }
-}
diff --git
a/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/wizards/any/AbstractResources.java
b/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/wizards/any/AbstractResources.java
deleted file mode 100644
index f6fde2dd45..0000000000
---
a/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/wizards/any/AbstractResources.java
+++ /dev/null
@@ -1,73 +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.ui.commons.wizards.any;
-
-import java.util.ArrayList;
-import java.util.List;
-import org.apache.commons.lang3.StringUtils;
-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.common.lib.to.AnyTO;
-import org.apache.wicket.extensions.wizard.WizardModel.ICondition;
-import org.apache.wicket.extensions.wizard.WizardStep;
-import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.model.PropertyModel;
-import org.apache.wicket.model.util.ListModel;
-
-public abstract class AbstractResources extends WizardStep implements
ICondition {
-
- private static final long serialVersionUID = 552437609667518888L;
-
- protected final AnyTO anyTO;
-
- protected final ListModel<String> available;
-
- public <T extends AnyTO> AbstractResources(final AnyWrapper<T>
modelObject) {
- anyTO = modelObject.getInnerObject();
-
- if (modelObject instanceof UserWrapper userWrapper
- && userWrapper.getPreviousUserTO() != null
- && !modelObject.getInnerObject().getResources().equals(
- userWrapper.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<>(anyTO, "resources") {
-
- private static final long serialVersionUID = 3799387950428254072L;
-
- @Override
- public List<String> getObject() {
- return new ArrayList<>(anyTO.getResources());
- }
-
- @Override
- public void setObject(final List<String> object) {
- anyTO.getResources().clear();
- anyTO.getResources().addAll(object);
- }
- }, available).hideLabel().setOutputMarkupId(true));
- }
-}
diff --git
a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AnyPanel.java
b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AnyPanel.java
index 7abaa5f20b..7851d41167 100644
---
a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AnyPanel.java
+++
b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AnyPanel.java
@@ -286,8 +286,7 @@ public class AnyPanel extends Panel implements ModalPanel {
pr).setRealm(realm).setDynRealm(dynRealm).setFiltered(true).
setFiql(fiql).setWizardInModal(true).addNewItemPanelBuilder(
AnyLayoutUtils.newLayoutInfo(anyObject,
anyType.getClasses(),
-
layout.getAnyObjects().get(anyType.getKey()),
- anyObjectRestClient, pr)).
+
layout.getAnyObjects().get(anyType.getKey()), anyObjectRestClient, pr)).
build(id);
MetaDataRoleAuthorizationStrategy.authorize(
panel, WebPage.RENDER,
AnyEntitlement.SEARCH.getFor(anyType.getKey()));
diff --git
a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyObjectWizardBuilder.java
b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyObjectWizardBuilder.java
index 5771d4af9c..a853252249 100644
---
a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyObjectWizardBuilder.java
+++
b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyObjectWizardBuilder.java
@@ -47,8 +47,8 @@ public class AnyObjectWizardBuilder extends
AnyWizardBuilder<AnyObjectTO> implem
final AnyObjectRestClient anyObjectRestClient,
final PageReference pageRef) {
- super(Optional.ofNullable(anyObjectTO).map(AnyObjectWrapper::new).
- orElse(null), anyTypeClasses, formLayoutInfo, pageRef);
+
super(Optional.ofNullable(anyObjectTO).map(AnyObjectWrapper::new).orElse(null),
+ anyTypeClasses, formLayoutInfo, pageRef);
this.anyObjectRestClient = anyObjectRestClient;
}
@@ -68,7 +68,8 @@ public class AnyObjectWizardBuilder extends
AnyWizardBuilder<AnyObjectTO> implem
final AnyObjectFormLayoutInfo formLayoutInfo,
final PageReference pageRef) {
- super(new AnyObjectWrapper(previousAnyObjectTO, anyObjectTO),
anyTypeClasses, formLayoutInfo, pageRef);
+ super(new AnyObjectWrapper(previousAnyObjectTO, anyObjectTO),
+ anyTypeClasses, formLayoutInfo, pageRef);
}
@Override
diff --git
a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyWizardBuilder.java
b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyWizardBuilder.java
index f62a8870de..07e129d470 100644
---
a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyWizardBuilder.java
+++
b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyWizardBuilder.java
@@ -30,11 +30,10 @@ import
org.apache.syncope.client.console.layout.GroupFormLayoutInfo;
import org.apache.syncope.client.console.layout.UserFormLayoutInfo;
import org.apache.syncope.client.ui.commons.layout.AbstractAnyFormLayout;
import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
-import
org.apache.syncope.client.ui.commons.wizards.any.AbstractAnyWizardBuilder;
+import org.apache.syncope.client.ui.commons.wizards.AjaxWizardBuilder;
import org.apache.syncope.client.ui.commons.wizards.any.AnyForm;
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.Attr;
import org.apache.syncope.common.lib.to.AnyObjectTO;
import org.apache.syncope.common.lib.to.AnyTO;
import org.apache.syncope.common.lib.to.GroupTO;
@@ -43,7 +42,7 @@ import org.apache.syncope.common.lib.to.UserTO;
import org.apache.wicket.PageReference;
import org.apache.wicket.extensions.wizard.WizardModel;
-public abstract class AnyWizardBuilder<A extends AnyTO> extends
AbstractAnyWizardBuilder<A> {
+public abstract class AnyWizardBuilder<A extends AnyTO> extends
AjaxWizardBuilder<AnyWrapper<A>> {
private static final long serialVersionUID = -2480279868319546243L;
@@ -60,14 +59,6 @@ public abstract class AnyWizardBuilder<A extends AnyTO>
extends AbstractAnyWizar
protected AbstractAnyFormLayout<A, ? extends AnyForm<A>> formLayoutInfo;
- /**
- * Construct.
- *
- * @param anyTO any
- * @param anyTypeClasses any type classes
- * @param formLayoutInfo form layout info
- * @param pageRef caller page reference.
- */
public AnyWizardBuilder(
final A anyTO,
final List<String> anyTypeClasses,
@@ -79,15 +70,7 @@ public abstract class AnyWizardBuilder<A extends AnyTO>
extends AbstractAnyWizar
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(
+ protected AnyWizardBuilder(
final AnyWrapper<A> wrapper,
final List<String> anyTypeClasses,
final AbstractAnyFormLayout<A, ? extends AnyForm<A>>
formLayoutInfo,
@@ -166,15 +149,12 @@ public abstract class AnyWizardBuilder<A extends AnyTO>
extends AbstractAnyWizar
}
}
- @Override
protected void fixPlainAttrs(final AnyTO updated, final AnyTO original) {
// re-add to the updated object any missing plain attribute (compared
to original): this to cope with
// form layout, which might have not included some plain attributes
- for (Attr plainAttr : original.getPlainAttrs()) {
- if (updated.getPlainAttr(plainAttr.getSchema()).isEmpty()) {
- updated.getPlainAttrs().add(plainAttr);
- }
- }
+ original.getPlainAttrs().stream().
+ filter(plainAttr ->
updated.getPlainAttr(plainAttr.getSchema()).isEmpty()).
+ forEach(updated.getPlainAttrs()::add);
if (updated instanceof GroupableRelatableTO updatedTO && original
instanceof GroupableRelatableTO originalTO) {
originalTO.getMemberships().
diff --git
a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/ConsoleAuxClasses.java
b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/ConsoleAuxClasses.java
index bdb8a6168f..3da0494071 100644
---
a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/ConsoleAuxClasses.java
+++
b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/ConsoleAuxClasses.java
@@ -19,14 +19,22 @@
package org.apache.syncope.client.console.wizards.any;
import java.util.List;
+import org.apache.commons.collections4.ListUtils;
+import org.apache.commons.lang3.StringUtils;
import org.apache.syncope.client.console.rest.AnyTypeClassRestClient;
-import org.apache.syncope.client.ui.commons.wizards.any.AbstractAuxClasses;
+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.lib.to.AnyTypeClassTO;
+import org.apache.wicket.extensions.wizard.WizardStep;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.model.PropertyModel;
+import org.apache.wicket.model.util.ListModel;
import org.apache.wicket.spring.injection.annot.SpringBean;
-public class ConsoleAuxClasses extends AbstractAuxClasses {
+public class ConsoleAuxClasses extends WizardStep {
private static final long serialVersionUID = 552437609667518888L;
@@ -34,11 +42,33 @@ public class ConsoleAuxClasses extends AbstractAuxClasses {
protected AnyTypeClassRestClient anyTypeClassRestClient;
public <T extends AnyTO> ConsoleAuxClasses(final AnyWrapper<T>
modelObject, final List<String> anyTypeClasses) {
- super(modelObject, anyTypeClasses);
- }
+ super();
+ setOutputMarkupId(true);
+
+ List<String> choices = anyTypeClassRestClient.list().stream().
+ map(AnyTypeClassTO::getKey).filter(aux ->
!anyTypeClasses.contains(aux)).
+ sorted().
+ toList();
+
+ add(new AjaxPalettePanel.Builder<String>().setAllowOrder(true).build(
+ "auxClasses",
+ new PropertyModel<>(modelObject.getInnerObject(),
"auxClasses"),
+ new ListModel<>(choices)).
+ hideLabel().setOutputMarkupId(true));
+
+ // ------------------
+ // insert changed label if needed
+ // ------------------
+ if (modelObject instanceof UserWrapper userWrapper
+ && userWrapper.getPreviousUserTO() != null
+ && !ListUtils.isEqualList(
+ userWrapper.getInnerObject().getAuxClasses(),
+ userWrapper.getPreviousUserTO().getAuxClasses())) {
- @Override
- protected List<AnyTypeClassTO> listAnyTypecClasses() {
- return anyTypeClassRestClient.list();
+ add(new LabelInfo("changed", StringUtils.EMPTY));
+ } else {
+ add(new Label("changed", StringUtils.EMPTY));
+ }
+ // ------------------
}
}
diff --git
a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/GroupWizardBuilder.java
b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/GroupWizardBuilder.java
index 83995f2726..5818189441 100644
---
a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/GroupWizardBuilder.java
+++
b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/GroupWizardBuilder.java
@@ -50,8 +50,8 @@ public class GroupWizardBuilder extends
AnyWizardBuilder<GroupTO> implements Gro
final GroupRestClient groupRestClient,
final PageReference pageRef) {
- super(Optional.ofNullable(groupTO).map(GroupWrapper::new).
- orElse(null), anyTypeClasses, formLayoutInfo, pageRef);
+ super(Optional.ofNullable(groupTO).map(GroupWrapper::new).orElse(null),
+ anyTypeClasses, formLayoutInfo, pageRef);
this.groupRestClient = groupRestClient;
}
@@ -71,7 +71,8 @@ public class GroupWizardBuilder extends
AnyWizardBuilder<GroupTO> implements Gro
final GroupFormLayoutInfo formLayoutInfo,
final PageReference pageRef) {
- super(new GroupWrapper(previousGroupTO, groupTO), anyTypeClasses,
formLayoutInfo, pageRef);
+ super(new GroupWrapper(previousGroupTO, groupTO),
+ anyTypeClasses, formLayoutInfo, pageRef);
}
/**
diff --git
a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/Groups.java
b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/Groups.java
index 2304d6dde4..f598cdd791 100644
---
a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/Groups.java
+++
b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/Groups.java
@@ -24,6 +24,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
+import org.apache.commons.collections4.ListUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.cxf.jaxrs.ext.search.client.CompleteCondition;
import org.apache.syncope.client.console.SyncopeConsoleSession;
@@ -32,10 +33,11 @@ import
org.apache.syncope.client.console.rest.GroupRestClient;
import org.apache.syncope.client.console.rest.SyncopeRestClient;
import org.apache.syncope.client.lib.SyncopeClient;
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.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.client.ui.commons.wizards.any.UserWrapper;
import org.apache.syncope.common.lib.SyncopeConstants;
import org.apache.syncope.common.lib.search.GroupFiqlSearchConditionBuilder;
import org.apache.syncope.common.lib.to.AnyTO;
@@ -47,6 +49,8 @@ import org.apache.syncope.common.lib.types.IdRepoEntitlement;
import
org.apache.wicket.authroles.authorization.strategies.role.metadata.ActionPermissions;
import
org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
import org.apache.wicket.extensions.markup.html.repeater.util.SortParam;
+import org.apache.wicket.extensions.wizard.WizardModel.ICondition;
+import org.apache.wicket.extensions.wizard.WizardStep;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.IChoiceRenderer;
@@ -55,16 +59,26 @@ import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.model.util.ListModel;
import org.apache.wicket.spring.injection.annot.SpringBean;
-public class Groups extends AbstractGroups {
+public class Groups extends WizardStep implements ICondition {
private static final long serialVersionUID = 552437609667518888L;
+ protected static final int MAX_GROUP_LIST_CARDINALITY = 30;
+
@SpringBean
protected GroupRestClient groupRestClient;
@SpringBean
protected SyncopeRestClient syncopeRestClient;
+ protected final AnyTO anyTO;
+
+ protected WebMarkupContainer dyngroupsContainer;
+
+ protected WebMarkupContainer dynrealmsContainer;
+
+ protected WebMarkupContainer groupsContainer;
+
protected final List<DynRealmTO> allDynRealms = new ArrayList<>();
protected final boolean templateMode;
@@ -74,7 +88,31 @@ public class Groups extends AbstractGroups {
protected AjaxPalettePanel.Builder<MembershipTO> groups;
public <T extends AnyTO> Groups(final AnyWrapper<T> modelObject, final
boolean templateMode) {
- super(modelObject);
+ super();
+ 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 final UserWrapper uw
+ && uw.getPreviousUserTO() != null
+ && !ListUtils.isEqualList(
+ uw.getInnerObject().getMemberships(),
+ uw.getPreviousUserTO().getMemberships())) {
+
+ groupsContainer.add(new LabelInfo("changed", StringUtils.EMPTY));
+ } else {
+ groupsContainer.add(new Label("changed", StringUtils.EMPTY));
+ }
+ // ------------------
+
this.templateMode = templateMode;
this.groupsModel = new ConsoleGroupsModel();
@@ -96,7 +134,6 @@ public class Groups extends AbstractGroups {
SyncopeConstants.ROOT_REALM, term, 1,
Constants.MAX_GROUP_LIST_SIZE);
}
- @Override
protected void addDynamicRealmsContainer() {
dynrealmsContainer = new WebMarkupContainer("dynrealmsContainer");
dynrealmsContainer.setOutputMarkupId(true);
@@ -108,7 +145,6 @@ public class Groups extends AbstractGroups {
add(dynrealmsContainer);
}
- @Override
protected void addGroupsPanel() {
if (anyTO instanceof GroupTO) {
groupsContainer.add(new Label("groups").setVisible(false));
@@ -179,7 +215,6 @@ public class Groups extends AbstractGroups {
}
}
- @Override
protected void addDynamicGroupsContainer() {
dyngroupsContainer = new WebMarkupContainer("dyngroupsContainer");
dyngroupsContainer.setOutputMarkupId(true);
diff --git
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyDataBinder.java
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyDataBinder.java
index 4a9757b878..f5d27b0594 100644
---
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyDataBinder.java
+++
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyDataBinder.java
@@ -366,23 +366,24 @@ abstract class AnyDataBinder extends
AttributableDataBinder {
}
}
- protected void fillAuxClasses(final Relatable<?, ?> any, final AnyUR
anyUR) {
- for (StringPatchItem patch : anyUR.getAuxClasses()) {
- anyTypeClassDAO.findById(patch.getValue()).ifPresentOrElse(
- auxClass -> {
- switch (patch.getOperation()) {
- case ADD_REPLACE:
- any.add(auxClass);
- break;
-
- case DELETE:
- default:
- any.getAuxClasses().remove(auxClass);
- }
- },
- () -> LOG.debug("Invalid {} {}, ignoring...",
- AnyTypeClass.class.getSimpleName(),
patch.getValue()));
- }
+ protected void processAuxClasses(final Relatable<?, ?> any, final AnyUR
anyUR) {
+ anyUR.getAuxClasses().forEach(patch ->
anyTypeClassDAO.findById(patch.getValue()).ifPresentOrElse(
+ auxClass -> {
+ switch (patch.getOperation()) {
+ case ADD_REPLACE:
+ any.add(auxClass);
+ break;
+
+ case DELETE:
+ default:
+ if (any.getAuxClasses().remove(auxClass)) {
+ auxClass.getPlainSchemas().
+ forEach(schema ->
any.getPlainAttr(schema.getKey()).ifPresent(any::remove));
+ }
+ }
+ },
+ () -> LOG.debug("Invalid {} {}, ignoring...",
+ AnyTypeClass.class.getSimpleName(),
patch.getValue())));
}
protected void fill(
diff --git
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyObjectDataBinderImpl.java
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyObjectDataBinderImpl.java
index baa7bbf1ad..e3d8931b3f 100644
---
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyObjectDataBinderImpl.java
+++
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyObjectDataBinderImpl.java
@@ -245,7 +245,7 @@ public class AnyObjectDataBinderImpl extends AnyDataBinder
implements AnyObjectD
@Override
public PropagationByResource<String> update(final AnyObject toBeUpdated,
final AnyObjectUR anyObjectUR) {
- fillAuxClasses(toBeUpdated, anyObjectUR);
+ processAuxClasses(toBeUpdated, anyObjectUR);
// Re-merge any pending change from workflow tasks
AnyObject anyObject = anyObjectDAO.save(toBeUpdated);
diff --git
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/GroupDataBinderImpl.java
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/GroupDataBinderImpl.java
index a6010aaef1..4528bd62c9 100644
---
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/GroupDataBinderImpl.java
+++
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/GroupDataBinderImpl.java
@@ -225,7 +225,7 @@ public class GroupDataBinderImpl extends AnyDataBinder
implements GroupDataBinde
@Override
public PropagationByResource<String> update(final Group toBeUpdated, final
GroupUR groupUR) {
- fillAuxClasses(toBeUpdated, groupUR);
+ processAuxClasses(toBeUpdated, groupUR);
// Re-merge any pending change from workflow tasks
Group group = groupDAO.save(toBeUpdated);
diff --git
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java
index 272459b573..63ee682f74 100644
---
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java
+++
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java
@@ -370,7 +370,7 @@ public class UserDataBinderImpl extends AnyDataBinder
implements UserDataBinder
@Override
public UserWorkflowResult.PropagationInfo update(final User toBeUpdated,
final UserUR userUR) {
- fillAuxClasses(toBeUpdated, userUR);
+ processAuxClasses(toBeUpdated, userUR);
// Re-merge any pending change from workflow tasks
User user = userDAO.save(toBeUpdated);
diff --git
a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/AnyObjectITCase.java
b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/AnyObjectITCase.java
index f6eea19886..b1f5466276 100644
---
a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/AnyObjectITCase.java
+++
b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/AnyObjectITCase.java
@@ -439,4 +439,38 @@ public class AnyObjectITCase extends AbstractITCase {
printer = updateAnyObject(printerUR).getEntity();
checkAnyTO.accept(printer);
}
+
+ @Test
+ public void issueSYNCOPE1960() {
+ // 1. create schema and class
+ PlainSchemaTO plainSchema = new PlainSchemaTO();
+ plainSchema.setKey("new_plain_schema" + getUUIDString());
+ plainSchema.setType(AttrSchemaType.String);
+ plainSchema = createSchema(SchemaType.PLAIN, plainSchema);
+
+ AnyTypeClassTO newClass = new AnyTypeClassTO();
+ newClass.setKey("new class" + getUUIDString());
+ newClass.getPlainSchemas().add(plainSchema.getKey());
+ ANY_TYPE_CLASS_SERVICE.create(newClass);
+
+ // 2. create printer with the new class as aux class
+ AnyObjectCR anyObjectCR = getSample("syncope1960");
+ anyObjectCR.getResources().clear();
+ anyObjectCR.getAuxClasses().add(newClass.getKey());
+ anyObjectCR.getPlainAttrs().add(attr(plainSchema.getKey(), "value"));
+
+ AnyObjectTO printer = createAnyObject(anyObjectCR).getEntity();
+ assertTrue(printer.getPlainAttr(plainSchema.getKey()).isPresent());
+ assertTrue(printer.getAuxClasses().contains(newClass.getKey()));
+
+ // 3. remove aux class
+ AnyObjectUR anyObjectUR = new AnyObjectUR.Builder(printer.getKey()).
+ auxClass(new
StringPatchItem.Builder().value(newClass.getKey()).
+ operation(PatchOperation.DELETE).build()).
+ build();
+
+ printer = updateAnyObject(anyObjectUR).getEntity();
+ assertTrue(printer.getPlainAttr(plainSchema.getKey()).isEmpty());
+ assertFalse(printer.getAuxClasses().contains(newClass.getKey()));
+ }
}
diff --git a/pom.xml b/pom.xml
index a479d00cbc..0e5127a876 100644
--- a/pom.xml
+++ b/pom.xml
@@ -451,7 +451,7 @@ under the License.
<disruptor.version>4.0.0</disruptor.version>
<elasticsearch.version>9.2.7</elasticsearch.version>
- <opensearch.version>3.5.0</opensearch.version>
+ <opensearch.version>3.6.0</opensearch.version>
<opensearch-java.version>3.8.0</opensearch-java.version>
<openfga.version>v1</openfga.version>