This is an automated email from the ASF dual-hosted git repository.

ilgrosso pushed a commit to branch 3_0_X
in repository https://gitbox.apache.org/repos/asf/syncope.git


The following commit(s) were added to refs/heads/3_0_X by this push:
     new 7519089223 [SYNCOPE-1889] improve group search using SCIM extension 
(#1125)
7519089223 is described below

commit 75190892234d76cf8667efbbfdbbc66730f7ccfa
Author: Samuel Garofalo <[email protected]>
AuthorDate: Thu Jul 3 16:48:36 2025 +0200

    [SYNCOPE-1889] improve group search using SCIM extension (#1125)
---
 .../syncope/core/persistence/api/dao/GroupDAO.java |  2 ++
 .../core/persistence/jpa/dao/JPAGroupDAO.java      | 13 +++++++++
 .../apache/syncope/core/logic/SCIMDataBinder.java  | 31 ++++++++++++---------
 .../syncope/core/logic/SCIMLogicContext.java       |  6 ++--
 .../syncope/core/logic/SCIMDataBinderTest.java     |  4 ++-
 .../org/apache/syncope/fit/core/SCIMITCase.java    | 32 ++++++++++++++++++++++
 6 files changed, 72 insertions(+), 16 deletions(-)

diff --git 
a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/GroupDAO.java
 
b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/GroupDAO.java
index bfc7b61813..a90831ec3c 100644
--- 
a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/GroupDAO.java
+++ 
b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/GroupDAO.java
@@ -59,6 +59,8 @@ public interface GroupDAO extends AnyDAO<Group> {
 
     List<UMembership> findUMemberships(Group group);
 
+    List<UMembership> findUMemberships(Group group, int page, int 
itemsPerPage);
+
     List<TypeExtension> findTypeExtensions(AnyTypeClass anyTypeClass);
 
     boolean existsAMembership(String anyObjectKey, String groupKey);
diff --git 
a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAGroupDAO.java
 
b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAGroupDAO.java
index ca834be3e7..fb6459876c 100644
--- 
a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAGroupDAO.java
+++ 
b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAGroupDAO.java
@@ -274,6 +274,19 @@ public class JPAGroupDAO extends AbstractAnyDAO<Group> 
implements GroupDAO {
         return query.getResultList();
     }
 
+    @Override
+    public List<UMembership> findUMemberships(final Group group, final int 
page, final int itemsPerPage) {
+        TypedQuery<UMembership> query = entityManager().createQuery(
+                "SELECT e FROM " + JPAUMembership.class.getSimpleName()
+                        + " e WHERE e.rightEnd=:group ORDER BY e.leftEnd",
+                UMembership.class);
+        query.setParameter("group", group);
+        query.setFirstResult(itemsPerPage * (page <= 0 ? 0 : page - 1));
+        query.setMaxResults(itemsPerPage);
+
+        return query.getResultList();
+    }
+
     @Override
     public List<Group> findAll(final int page, final int itemsPerPage) {
         TypedQuery<Group> query = entityManager().createQuery(
diff --git 
a/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/SCIMDataBinder.java
 
b/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/SCIMDataBinder.java
index 06c3c59a41..7c37d03a3c 100644
--- 
a/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/SCIMDataBinder.java
+++ 
b/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/SCIMDataBinder.java
@@ -55,8 +55,11 @@ import org.apache.syncope.common.lib.types.PatchOperation;
 import org.apache.syncope.common.lib.types.StatusRType;
 import org.apache.syncope.core.logic.scim.SCIMConfManager;
 import org.apache.syncope.core.persistence.api.dao.AnyDAO;
+import org.apache.syncope.core.persistence.api.dao.GroupDAO;
+import org.apache.syncope.core.persistence.api.dao.NotFoundException;
 import org.apache.syncope.core.persistence.api.dao.search.MembershipCond;
 import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
+import org.apache.syncope.core.persistence.api.entity.user.UMembership;
 import org.apache.syncope.core.provisioning.api.jexl.JexlUtils;
 import org.apache.syncope.core.spring.security.AuthDataAccessor;
 import org.apache.syncope.ext.scimv2.api.BadRequestException;
@@ -79,6 +82,7 @@ import org.apache.syncope.ext.scimv2.api.type.PatchOp;
 import org.apache.syncope.ext.scimv2.api.type.Resource;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.CollectionUtils;
 
 public class SCIMDataBinder {
@@ -123,14 +127,18 @@ public class SCIMDataBinder {
 
     protected final AuthDataAccessor authDataAccessor;
 
+    protected final GroupDAO groupDAO;
+
     public SCIMDataBinder(
             final SCIMConfManager confManager,
             final UserLogic userLogic,
-            final AuthDataAccessor authDataAccessor) {
+            final AuthDataAccessor authDataAccessor,
+            final GroupDAO groupDAO) {
 
         this.confManager = confManager;
         this.userLogic = userLogic;
         this.authDataAccessor = authDataAccessor;
+        this.groupDAO = groupDAO;
     }
 
     protected <E extends Enum<?>> void fill(
@@ -1019,6 +1027,7 @@ public class SCIMDataBinder {
         return Pair.of(userUR, statusR);
     }
 
+    @Transactional(readOnly = true)
     public SCIMGroup toSCIMGroup(
             final GroupTO groupTO,
             final String location,
@@ -1059,19 +1068,15 @@ public class SCIMDataBinder {
                     searchCond, 1, 1, List.of(), SyncopeConstants.ROOT_REALM, 
true, false).getLeft();
 
             for (int page = 1; page <= (count / AnyDAO.DEFAULT_PAGE_SIZE) + 1; 
page++) {
-                List<UserTO> users = userLogic.search(
-                        searchCond,
+                List<UMembership> users = groupDAO.findUMemberships(
+                        Optional.ofNullable(groupDAO.find(groupTO.getKey()))
+                                .orElseThrow(() -> new 
NotFoundException("Group " + groupTO.getKey())),
                         page,
-                        AnyDAO.DEFAULT_PAGE_SIZE,
-                        List.of(),
-                        SyncopeConstants.ROOT_REALM,
-                        true,
-                        false).
-                        getRight();
-                users.forEach(userTO -> group.getMembers().add(new Member(
-                        userTO.getKey(),
-                        StringUtils.substringBefore(location, "/Groups") + 
"/Users/" + userTO.getKey(),
-                        userTO.getUsername())));
+                        AnyDAO.DEFAULT_PAGE_SIZE);
+                users.forEach(uMembership -> group.getMembers().add(new Member(
+                        uMembership.getLeftEnd().getKey(),
+                        StringUtils.substringBefore(location, "/Groups") + 
"/Users/" + uMembership.getKey(),
+                        uMembership.getLeftEnd().getUsername())));
             }
         }
 
diff --git 
a/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/SCIMLogicContext.java
 
b/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/SCIMLogicContext.java
index 559146e273..968dd69dfc 100644
--- 
a/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/SCIMLogicContext.java
+++ 
b/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/SCIMLogicContext.java
@@ -21,6 +21,7 @@ package org.apache.syncope.core.logic;
 import org.apache.syncope.common.keymaster.client.api.ConfParamOps;
 import org.apache.syncope.core.logic.init.SCIMLoader;
 import org.apache.syncope.core.logic.scim.SCIMConfManager;
+import org.apache.syncope.core.persistence.api.dao.GroupDAO;
 import org.apache.syncope.core.spring.security.AuthDataAccessor;
 import 
org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
 import org.springframework.context.annotation.Bean;
@@ -46,9 +47,10 @@ public class SCIMLogicContext {
     public SCIMDataBinder scimDataBinder(
             final SCIMConfManager confManager,
             final UserLogic userLogic,
-            final AuthDataAccessor authDataAccessor) {
+            final AuthDataAccessor authDataAccessor,
+            final GroupDAO groupDAO) {
 
-        return new SCIMDataBinder(confManager, userLogic, authDataAccessor);
+        return new SCIMDataBinder(confManager, userLogic, authDataAccessor,  
groupDAO);
     }
 
     @ConditionalOnMissingBean
diff --git 
a/ext/scimv2/logic/src/test/java/org/apache/syncope/core/logic/SCIMDataBinderTest.java
 
b/ext/scimv2/logic/src/test/java/org/apache/syncope/core/logic/SCIMDataBinderTest.java
index c3f378c147..d65e4b9d63 100644
--- 
a/ext/scimv2/logic/src/test/java/org/apache/syncope/core/logic/SCIMDataBinderTest.java
+++ 
b/ext/scimv2/logic/src/test/java/org/apache/syncope/core/logic/SCIMDataBinderTest.java
@@ -27,6 +27,7 @@ import java.util.stream.Stream;
 import org.apache.syncope.common.lib.scim.SCIMConf;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.core.logic.scim.SCIMConfManager;
+import org.apache.syncope.core.persistence.api.dao.GroupDAO;
 import org.apache.syncope.core.spring.security.AuthDataAccessor;
 import org.apache.syncope.ext.scimv2.api.data.SCIMPatchOperation;
 import org.apache.syncope.ext.scimv2.api.data.SCIMPatchPath;
@@ -50,7 +51,8 @@ class SCIMDataBinderTest {
         when(scimConfManager.get()).thenReturn(new SCIMConf());
         UserLogic userLogic = mock(UserLogic.class);
         AuthDataAccessor authDataAccessor = mock(AuthDataAccessor.class);
-        dataBinder = new SCIMDataBinder(scimConfManager, userLogic, 
authDataAccessor);
+        GroupDAO  groupDAO = mock(GroupDAO.class);
+        dataBinder = new SCIMDataBinder(scimConfManager, userLogic, 
authDataAccessor,  groupDAO);
     }
 
     @ParameterizedTest
diff --git 
a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SCIMITCase.java 
b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SCIMITCase.java
index 4fc1db575f..c9c705db93 100644
--- 
a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SCIMITCase.java
+++ 
b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SCIMITCase.java
@@ -45,6 +45,7 @@ import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.Response;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.cxf.jaxrs.client.WebClient;
+import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.request.GroupUR;
 import org.apache.syncope.common.lib.request.StringPatchItem;
 import org.apache.syncope.common.lib.request.UserUR;
@@ -63,6 +64,7 @@ import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.types.PatchOperation;
 import org.apache.syncope.common.rest.api.Preference;
 import org.apache.syncope.common.rest.api.RESTHeaders;
+import org.apache.syncope.common.rest.api.beans.AnyQuery;
 import org.apache.syncope.ext.scimv2.api.SCIMConstants;
 import org.apache.syncope.ext.scimv2.api.data.Group;
 import org.apache.syncope.ext.scimv2.api.data.ListResponse;
@@ -385,6 +387,36 @@ public class SCIMITCase extends AbstractITCase {
 
         SCIMGroup additional = groups.getResources().get(0);
         assertEquals("additional", additional.getDisplayName());
+        List<UserTO> usersList = USER_SERVICE.search(new AnyQuery.Builder()
+                .realm(SyncopeConstants.ROOT_REALM)
+                .page(0)
+                .size(15)
+                .fiql("$groups==additional")
+                .build()).getResult();
+        assertEquals(usersList.size(), additional.getMembers().size());
+
+        // eq to get members
+        response = webClient().path("Groups").query("filter", "displayName eq 
\"child\"").get();
+        assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
+        assertEquals(
+                SCIMConstants.APPLICATION_SCIM_JSON,
+                
StringUtils.substringBefore(response.getHeaderString(HttpHeaders.CONTENT_TYPE), 
";"));
+
+        groups = response.readEntity(new GenericType<>() {
+        });
+        assertNotNull(groups);
+        assertEquals(1, groups.getTotalResults());
+
+        SCIMGroup child = groups.getResources().get(0);
+        assertEquals("child", child.getDisplayName());
+        usersList = USER_SERVICE.search(new AnyQuery.Builder()
+                .realm(SyncopeConstants.ROOT_REALM)
+                .page(0)
+                .size(15)
+                .fiql("$groups==child")
+                .build()).getResult();
+        assertEquals(usersList.size(), child.getMembers().size());
+        assertTrue(child.getMembers().stream().anyMatch(member -> 
member.getDisplay().equals("verdi")));
 
         // eq via POST
         SCIMSearchRequest request = new SCIMSearchRequest("displayName eq 
\"additional\"", null, null, null, null);

Reply via email to