You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by il...@apache.org on 2026/04/27 09:50:51 UTC
(syncope) branch 4_1_X updated: [SYNCOPE-1921] LDAPMembershipPropagationActions preserves external group memberships (#1362)
This is an automated email from the ASF dual-hosted git repository.
ilgrosso pushed a commit to branch 4_1_X
in repository https://gitbox.apache.org/repos/asf/syncope.git
The following commit(s) were added to refs/heads/4_1_X by this push:
new e64b2ee986 [SYNCOPE-1921] LDAPMembershipPropagationActions preserves external group memberships (#1362)
e64b2ee986 is described below
commit e64b2ee986f30673416cf578e6705fdfaf795045
Author: Oleg Zimakov <ol...@zimakov.net>
AuthorDate: Mon Apr 27 02:49:22 2026 -0700
[SYNCOPE-1921] LDAPMembershipPropagationActions preserves external group memberships (#1362)
---
.../LDAPMembershipPropagationActions.java | 5 ++
.../syncope/fit/core/PropagationTaskITCase.java | 80 ++++++++++++++++++++++
2 files changed, 85 insertions(+)
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/LDAPMembershipPropagationActions.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/LDAPMembershipPropagationActions.java
index d4c5f310e4..634c5afe1f 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/LDAPMembershipPropagationActions.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/LDAPMembershipPropagationActions.java
@@ -87,6 +87,11 @@ public class LDAPMembershipPropagationActions implements PropagationActions {
return "ldapGroups";
}
+ @Override
+ public Set<String> moreAttrsToGet(final Optional<PropagationTaskInfo> taskInfo, final Provision provision) {
+ return Set.of(getGroupMembershipAttrName());
+ }
+
protected String evaluateGroupConnObjectLink(final String connObjectLinkTemplate, final Group group) {
LOG.debug("Evaluating connObjectLink for {}", group);
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PropagationTaskITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PropagationTaskITCase.java
index c8e251048f..24308696e0 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PropagationTaskITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PropagationTaskITCase.java
@@ -976,6 +976,86 @@ public class PropagationTaskITCase extends AbstractTaskITCase {
}
}
+ @Test
+ public void issueSYNCOPE1921() {
+ ResourceTO ldap = RESOURCE_SERVICE.read(RESOURCE_NAME_LDAP);
+ UserTO userTO = null;
+ try {
+ // 1. clone the LDAP resource (which has LDAPMembershipPropagationActions configured)
+ // but do NOT add ldapGroups to the user mapping - rely solely on the propagation action
+ Provision provisionGroup =
+ SerializationUtils.clone(ldap.getProvision(AnyTypeKind.GROUP.name()).orElse(null));
+ assertNotNull(provisionGroup);
+
+ Provision provisionUser =
+ SerializationUtils.clone(ldap.getProvision(AnyTypeKind.USER.name()).orElse(null));
+ assertNotNull(provisionUser);
+ provisionUser.getMapping().getItems().removeIf(item -> "mail".equals(item.getExtAttrName()));
+
+ ldap.getProvisions().clear();
+ ldap.getProvisions().add(provisionUser);
+ ldap.getProvisions().add(provisionGroup);
+ ldap.setKey(RESOURCE_NAME_LDAP + "1921" + getUUIDString());
+ RESOURCE_SERVICE.create(ldap);
+
+ // 2. create group with the new resource assigned
+ GroupCR groupCR = new GroupCR();
+ groupCR.setName("SYNCOPEGROUP1921-" + getUUIDString());
+ groupCR.setRealm(SyncopeConstants.ROOT_REALM);
+ groupCR.getResources().add(ldap.getKey());
+
+ GroupTO groupTO = createGroup(groupCR).getEntity();
+ assertNotNull(groupTO);
+
+ // 3. create user with the new resource and group membership
+ UserCR userCR = UserITCase.getUniqueSample("syncope1921@syncope.apache.org");
+ userCR.getResources().clear();
+ userCR.getResources().add(ldap.getKey());
+ userCR.getMemberships().add(new MembershipTO.Builder(groupTO.getKey()).build());
+
+ userTO = createUser(userCR).getEntity();
+ assertNotNull(userTO);
+
+ // 4. deassociate and delete group from Syncope, leaving the LDAP group entry orphaned
+ ResourceDR resourceDR = new ResourceDR.Builder().key(groupTO.getKey()).
+ action(ResourceDeassociationAction.UNLINK).resource(ldap.getKey()).build();
+
+ GROUP_SERVICE.deassociate(resourceDR);
+ GROUP_SERVICE.delete(groupTO.getKey());
+
+ // 5. create a new group and assign user to it
+ GroupCR newGroupCR = new GroupCR();
+ newGroupCR.setName("NEWSYNCOPEGROUP1921-" + getUUIDString());
+ newGroupCR.setRealm(SyncopeConstants.ROOT_REALM);
+ newGroupCR.getResources().add(ldap.getKey());
+
+ GroupTO newGroupTO = createGroup(newGroupCR).getEntity();
+ assertNotNull(newGroupTO);
+
+ UserUR userUR = new UserUR();
+ userUR.setKey(userTO.getKey());
+ userUR.getMemberships().add(
+ new MembershipUR.Builder(newGroupTO.getKey()).operation(PatchOperation.ADD_REPLACE).build());
+ USER_SERVICE.update(userUR);
+
+ // 6. verify that the orphaned group membership was preserved during propagation
+ ConnObject connObject =
+ RESOURCE_SERVICE.readConnObject(ldap.getKey(), AnyTypeKind.USER.name(), userTO.getKey());
+ assertNotNull(connObject);
+ assertTrue(connObject.getAttr("ldapGroups").isPresent());
+ assertEquals(2, connObject.getAttr("ldapGroups").orElseThrow().getValues().size());
+ } finally {
+ try {
+ RESOURCE_SERVICE.delete(ldap.getKey());
+ if (userTO != null) {
+ USER_SERVICE.delete(userTO.getKey());
+ }
+ } catch (Exception ignore) {
+ // ignore
+ }
+ }
+ }
+
@Test
public void issueSYNCOPE1751() {
// 1. Create a Group with a resource assigned