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);