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 2022/05/23 12:13:44 UTC
[syncope] branch master updated: [SYNCOPE-1678] Adding recursive boolean parameter to AnyQuery, true b… (#346)
This is an automated email from the ASF dual-hosted git repository.
ilgrosso pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/syncope.git
The following commit(s) were added to refs/heads/master by this push:
new 8a2690568f [SYNCOPE-1678] Adding recursive boolean parameter to AnyQuery, true b… (#346)
8a2690568f is described below
commit 8a2690568f7e3653a7112c0bdf795654efb236c5
Author: Francesco Chicchiriccò <il...@users.noreply.github.com>
AuthorDate: Mon May 23 14:13:33 2022 +0200
[SYNCOPE-1678] Adding recursive boolean parameter to AnyQuery, true b… (#346)
---
.../syncope/common/rest/api/beans/AnyQuery.java | 23 +++++-
.../common/rest/api/service/JAXRSService.java | 2 +
.../syncope/core/logic/ReconciliationLogic.java | 11 ++-
.../core/logic/ReconciliationLogicTest.java | 2 +-
.../syncope/core/logic/AbstractAnyLogic.java | 1 +
.../apache/syncope/core/logic/AnyObjectLogic.java | 11 ++-
.../org/apache/syncope/core/logic/GroupLogic.java | 10 ++-
.../syncope/core/logic/IdRepoLogicContext.java | 2 +
.../org/apache/syncope/core/logic/RealmLogic.java | 15 ++--
.../apache/syncope/core/logic/SyncopeLogic.java | 19 ++++-
.../org/apache/syncope/core/logic/UserLogic.java | 10 ++-
.../core/rest/cxf/service/AbstractAnyService.java | 1 +
.../rest/cxf/service/AnyObjectServiceTest.java | 4 +-
.../core/persistence/api/dao/AnySearchDAO.java | 22 +++++-
.../persistence/jpa/dao/PGJPAJSONAnySearchDAO.java | 16 +++-
.../persistence/jpa/dao/AbstractAnySearchDAO.java | 26 ++++--
.../core/persistence/jpa/dao/JPAAnySearchDAO.java | 70 ++++++++++------
.../core/persistence/jpa/dao/JPAGroupDAO.java | 10 ++-
.../core/persistence/jpa/inner/AnySearchTest.java | 68 ++++++++++------
.../core/persistence/jpa/outer/AnySearchTest.java | 7 +-
.../java/job/report/GroupReportlet.java | 41 ++++++----
.../java/job/report/ReconciliationReportlet.java | 31 +++++++-
.../java/job/report/UserReportlet.java | 45 +++++++----
.../pushpull/DefaultRealmPullResultHandler.java | 9 ++-
.../java/pushpull/PushJobDelegate.java | 4 +
.../jpa/dao/ElasticsearchAnySearchDAO.java | 92 +++++++++++++++-------
.../jpa/dao/ElasticsearchAnySearchDAOTest.java | 9 ++-
.../apache/syncope/core/logic/SCIMDataBinder.java | 4 +-
.../ext/scimv2/cxf/service/AbstractService.java | 1 +
.../ext/scimv2/cxf/service/GroupServiceImpl.java | 4 +-
.../org/apache/syncope/fit/core/SearchITCase.java | 7 ++
pom.xml | 4 +-
32 files changed, 411 insertions(+), 170 deletions(-)
diff --git a/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/beans/AnyQuery.java b/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/beans/AnyQuery.java
index fa5822336f..b9583785b0 100644
--- a/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/beans/AnyQuery.java
+++ b/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/beans/AnyQuery.java
@@ -21,6 +21,7 @@ package org.apache.syncope.common.rest.api.beans;
import io.swagger.v3.oas.annotations.ExternalDocumentation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Schema;
+import java.util.Optional;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.QueryParam;
import org.apache.commons.lang3.builder.EqualsBuilder;
@@ -28,8 +29,6 @@ import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.syncope.common.lib.SyncopeConstants;
import org.apache.syncope.common.rest.api.service.JAXRSService;
-import java.util.Optional;
-
public class AnyQuery extends AbstractQuery {
private static final long serialVersionUID = -6736562952418964707L;
@@ -41,6 +40,11 @@ public class AnyQuery extends AbstractQuery {
return new AnyQuery();
}
+ public Builder recursive(final boolean recursive) {
+ getInstance().setRecursive(recursive);
+ return this;
+ }
+
public Builder details(final boolean details) {
getInstance().setDetails(details);
return this;
@@ -60,6 +64,8 @@ public class AnyQuery extends AbstractQuery {
private String realm;
+ private Boolean recursive;
+
private Boolean details;
private String fiql;
@@ -79,6 +85,19 @@ public class AnyQuery extends AbstractQuery {
this.realm = realm;
}
+ @Parameter(name = JAXRSService.PARAM_RECURSIVE, description = "whether search results shall be returned from "
+ + "given realm and all children realms, or just the given realm", schema =
+ @Schema(implementation = Boolean.class))
+ public Boolean getRecursive() {
+ return Optional.ofNullable(recursive).orElse(Boolean.TRUE);
+ }
+
+ @QueryParam(JAXRSService.PARAM_RECURSIVE)
+ @DefaultValue("true")
+ public void setRecursive(final Boolean recursive) {
+ this.recursive = recursive;
+ }
+
@Parameter(name = JAXRSService.PARAM_DETAILS, description = "whether detailed information is to be included, "
+ "if applicable, about virtual attributes, (dynamic) roles, privileges, relationships, "
+ "(dynamic) memberships or linked accounts", schema =
diff --git a/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/JAXRSService.java b/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/JAXRSService.java
index 6ebdfd3baf..51a59cc576 100644
--- a/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/JAXRSService.java
+++ b/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/JAXRSService.java
@@ -40,6 +40,8 @@ public interface JAXRSService {
String PARAM_REALM = "realm";
+ String PARAM_RECURSIVE = "recursive";
+
String PARAM_DETAILS = "details";
String PARAM_CONNID_PAGED_RESULTS_COOKIE = "connIdPagedResultsCookie";
diff --git a/core/idm/logic/src/main/java/org/apache/syncope/core/logic/ReconciliationLogic.java b/core/idm/logic/src/main/java/org/apache/syncope/core/logic/ReconciliationLogic.java
index ef3deee89b..a7532c4363 100644
--- a/core/idm/logic/src/main/java/org/apache/syncope/core/logic/ReconciliationLogic.java
+++ b/core/idm/logic/src/main/java/org/apache/syncope/core/logic/ReconciliationLogic.java
@@ -68,6 +68,7 @@ import org.apache.syncope.core.persistence.api.dao.VirSchemaDAO;
import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
import org.apache.syncope.core.persistence.api.entity.AnyUtils;
+import org.apache.syncope.core.persistence.api.entity.Realm;
import org.apache.syncope.core.persistence.api.entity.VirSchema;
import org.apache.syncope.core.provisioning.api.ConnectorManager;
import org.apache.syncope.core.provisioning.api.pushpull.ConstantReconFilterBuilder;
@@ -568,6 +569,9 @@ public class ReconciliationLogic extends AbstractTransactionalLogic<EntityTO> {
entitlement = IdRepoEntitlement.USER_SEARCH;
}
+ Realm base = Optional.ofNullable(realmDAO.findByFullPath(realm)).
+ orElseThrow(() -> new NotFoundException("Realm " + realm));
+
Set<String> adminRealms = RealmUtils.getEffective(AuthContextUtils.getAuthorizations().get(entitlement), realm);
SearchCond effectiveCond = searchCond == null ? anyUtils.dao().getAllMatchingCond() : searchCond;
@@ -575,15 +579,16 @@ public class ReconciliationLogic extends AbstractTransactionalLogic<EntityTO> {
if (spec.getIgnorePaging()) {
matching = new ArrayList<>();
- int count = anySearchDAO.count(adminRealms, effectiveCond, anyType.getKind());
+ int count = anySearchDAO.count(base, true, adminRealms, effectiveCond, anyType.getKind());
int pages = (count / AnyDAO.DEFAULT_PAGE_SIZE) + 1;
for (int p = 1; p <= pages; p++) {
- matching.addAll(anySearchDAO.search(adminRealms, effectiveCond,
+ matching.addAll(anySearchDAO.search(base, true, adminRealms, effectiveCond,
p, AnyDAO.DEFAULT_PAGE_SIZE, orderBy, anyType.getKind()));
}
} else {
- matching = anySearchDAO.search(adminRealms, effectiveCond, page, size, orderBy, anyType.getKind());
+ matching = anySearchDAO.search(
+ base, true, adminRealms, effectiveCond, page, size, orderBy, anyType.getKind());
}
List<String> columns = new ArrayList<>();
diff --git a/core/idm/logic/src/test/java/org/apache/syncope/core/logic/ReconciliationLogicTest.java b/core/idm/logic/src/test/java/org/apache/syncope/core/logic/ReconciliationLogicTest.java
index 7fb1f9e731..174d347cbd 100644
--- a/core/idm/logic/src/test/java/org/apache/syncope/core/logic/ReconciliationLogicTest.java
+++ b/core/idm/logic/src/test/java/org/apache/syncope/core/logic/ReconciliationLogicTest.java
@@ -89,7 +89,7 @@ public class ReconciliationLogicTest extends AbstractTest {
@Test
public void pushToCSV() throws IOException {
Pair<Integer, List<UserTO>> search = AuthContextUtils.callAsAdmin(SyncopeConstants.MASTER_DOMAIN,
- () -> userLogic.search(null, 1, 100, List.of(), SyncopeConstants.ROOT_REALM, false));
+ () -> userLogic.search(null, 1, 100, List.of(), SyncopeConstants.ROOT_REALM, true, false));
assertNotNull(search);
CSVPushSpec spec = new CSVPushSpec.Builder(AnyTypeKind.USER.name()).ignorePaging(true).
diff --git a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/AbstractAnyLogic.java b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/AbstractAnyLogic.java
index 47b393ec82..7469722d5d 100644
--- a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/AbstractAnyLogic.java
+++ b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/AbstractAnyLogic.java
@@ -212,6 +212,7 @@ public abstract class AbstractAnyLogic<TO extends AnyTO, C extends AnyCR, U exte
SearchCond searchCond,
int page, int size, List<OrderByClause> orderBy,
String realm,
+ boolean recursive,
boolean details);
public abstract ProvisioningResult<TO> update(U updateReq, boolean nullPriorityAsync);
diff --git a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/AnyObjectLogic.java b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/AnyObjectLogic.java
index 71271cca2f..d26222b469 100644
--- a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/AnyObjectLogic.java
+++ b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/AnyObjectLogic.java
@@ -22,6 +22,7 @@ import java.lang.reflect.Method;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
+import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import org.apache.commons.lang3.ArrayUtils;
@@ -42,10 +43,12 @@ import org.apache.syncope.common.lib.types.PatchOperation;
import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
import org.apache.syncope.core.persistence.api.dao.AnySearchDAO;
import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
+import org.apache.syncope.core.persistence.api.dao.NotFoundException;
import org.apache.syncope.core.persistence.api.dao.RealmDAO;
import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
import org.apache.syncope.core.persistence.api.entity.AnyType;
+import org.apache.syncope.core.persistence.api.entity.Realm;
import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
import org.apache.syncope.core.provisioning.api.AnyObjectProvisioningManager;
import org.apache.syncope.core.provisioning.api.LogicActions;
@@ -98,20 +101,24 @@ public class AnyObjectLogic extends AbstractAnyLogic<AnyObjectTO, AnyObjectCR, A
final SearchCond searchCond,
final int page, final int size, final List<OrderByClause> orderBy,
final String realm,
+ final boolean recursive,
final boolean details) {
if (searchCond.hasAnyTypeCond() == null) {
throw new UnsupportedOperationException("Need to specify " + AnyType.class.getSimpleName());
}
+ Realm base = Optional.ofNullable(realmDAO.findByFullPath(realm)).
+ orElseThrow(() -> new NotFoundException("Realm " + realm));
+
Set<String> authRealms = RealmUtils.getEffective(
AuthContextUtils.getAuthorizations().get(AnyEntitlement.SEARCH.getFor(searchCond.hasAnyTypeCond())),
realm);
- int count = searchDAO.count(authRealms, searchCond, AnyTypeKind.ANY_OBJECT);
+ int count = searchDAO.count(base, recursive, authRealms, searchCond, AnyTypeKind.ANY_OBJECT);
List<AnyObject> matching = searchDAO.search(
- authRealms, searchCond, page, size, orderBy, AnyTypeKind.ANY_OBJECT);
+ base, recursive, authRealms, searchCond, page, size, orderBy, AnyTypeKind.ANY_OBJECT);
List<AnyObjectTO> result = matching.stream().
map(anyObject -> binder.getAnyObjectTO(anyObject, details)).
collect(Collectors.toList());
diff --git a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/GroupLogic.java b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/GroupLogic.java
index dcab7dec61..df16b30c9d 100644
--- a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/GroupLogic.java
+++ b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/GroupLogic.java
@@ -23,6 +23,7 @@ import java.time.OffsetDateTime;
import java.util.Collection;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import org.apache.commons.lang3.ArrayUtils;
@@ -56,6 +57,7 @@ import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
import org.apache.syncope.core.persistence.api.entity.EntityFactory;
import org.apache.syncope.core.persistence.api.entity.Implementation;
+import org.apache.syncope.core.persistence.api.entity.Realm;
import org.apache.syncope.core.persistence.api.entity.group.Group;
import org.apache.syncope.core.persistence.api.entity.task.SchedTask;
import org.apache.syncope.core.provisioning.api.GroupProvisioningManager;
@@ -167,17 +169,21 @@ public class GroupLogic extends AbstractAnyLogic<GroupTO, GroupCR, GroupUR> {
final SearchCond searchCond,
final int page, final int size, final List<OrderByClause> orderBy,
final String realm,
+ final boolean recursive,
final boolean details) {
+ Realm base = Optional.ofNullable(realmDAO.findByFullPath(realm)).
+ orElseThrow(() -> new NotFoundException("Realm " + realm));
+
Set<String> authRealms = RealmUtils.getEffective(
AuthContextUtils.getAuthorizations().get(IdRepoEntitlement.GROUP_SEARCH), realm);
SearchCond effectiveCond = searchCond == null ? groupDAO.getAllMatchingCond() : searchCond;
- int count = searchDAO.count(authRealms, effectiveCond, AnyTypeKind.GROUP);
+ int count = searchDAO.count(base, recursive, authRealms, effectiveCond, AnyTypeKind.GROUP);
List<Group> matching = searchDAO.search(
- authRealms, effectiveCond, page, size, orderBy, AnyTypeKind.GROUP);
+ base, recursive, authRealms, effectiveCond, page, size, orderBy, AnyTypeKind.GROUP);
List<GroupTO> result = matching.stream().
map(group -> binder.getGroupTO(group, details)).
collect(Collectors.toList());
diff --git a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/IdRepoLogicContext.java b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/IdRepoLogicContext.java
index bbb7d88b2d..a6cbdfcf17 100644
--- a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/IdRepoLogicContext.java
+++ b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/IdRepoLogicContext.java
@@ -426,6 +426,7 @@ public class IdRepoLogicContext {
public SyncopeLogic syncopeLogic(
final ContentExporter exporter,
final UserWorkflowAdapter uwfAdapter,
+ final RealmDAO realmDAO,
final AnyTypeDAO anyTypeDAO,
final GroupDAO groupDAO,
final ConfParamOps confParamOps,
@@ -435,6 +436,7 @@ public class IdRepoLogicContext {
final AnyObjectWorkflowAdapter awfAdapter) {
return new SyncopeLogic(
+ realmDAO,
anyTypeDAO,
groupDAO,
anySearchDAO,
diff --git a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/RealmLogic.java b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/RealmLogic.java
index bd1a0a96f6..1f49db7b45 100644
--- a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/RealmLogic.java
+++ b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/RealmLogic.java
@@ -21,6 +21,7 @@ package org.apache.syncope.core.logic;
import java.lang.reflect.Method;
import java.util.Comparator;
import java.util.List;
+import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import org.apache.commons.lang3.ArrayUtils;
@@ -189,12 +190,8 @@ public class RealmLogic extends AbstractTransactionalLogic<RealmTO> {
@PreAuthorize("hasRole('" + IdRepoEntitlement.REALM_DELETE + "')")
public ProvisioningResult<RealmTO> delete(final String fullPath) {
- Realm realm = realmDAO.findByFullPath(fullPath);
- if (realm == null) {
- LOG.error("Could not find realm '" + fullPath + '\'');
-
- throw new NotFoundException(fullPath);
- }
+ Realm realm = Optional.ofNullable(realmDAO.findByFullPath(fullPath)).
+ orElseThrow(() -> new NotFoundException("Realm " + fullPath));
if (!realmDAO.findChildren(realm).isEmpty()) {
throw SyncopeClientException.build(ClientExceptionType.HasChildren);
@@ -204,9 +201,9 @@ public class RealmLogic extends AbstractTransactionalLogic<RealmTO> {
AnyCond keyCond = new AnyCond(AttrCond.Type.ISNOTNULL);
keyCond.setSchema("key");
SearchCond allMatchingCond = SearchCond.getLeaf(keyCond);
- int users = searchDAO.count(adminRealms, allMatchingCond, AnyTypeKind.USER);
- int groups = searchDAO.count(adminRealms, allMatchingCond, AnyTypeKind.GROUP);
- int anyObjects = searchDAO.count(adminRealms, allMatchingCond, AnyTypeKind.ANY_OBJECT);
+ int users = searchDAO.count(realm, true, adminRealms, allMatchingCond, AnyTypeKind.USER);
+ int groups = searchDAO.count(realm, true, adminRealms, allMatchingCond, AnyTypeKind.GROUP);
+ int anyObjects = searchDAO.count(realm, true, adminRealms, allMatchingCond, AnyTypeKind.ANY_OBJECT);
if (users + groups + anyObjects > 0) {
SyncopeClientException containedAnys = SyncopeClientException.build(ClientExceptionType.AssociatedAnys);
diff --git a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/SyncopeLogic.java b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/SyncopeLogic.java
index b90aefd5d8..167840cadf 100644
--- a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/SyncopeLogic.java
+++ b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/SyncopeLogic.java
@@ -37,11 +37,13 @@ import org.apache.syncope.core.persistence.api.dao.AnySearchDAO;
import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
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.RealmDAO;
import org.apache.syncope.core.persistence.api.dao.search.AnyCond;
import org.apache.syncope.core.persistence.api.dao.search.AssignableCond;
import org.apache.syncope.core.persistence.api.dao.search.AttrCond;
import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
+import org.apache.syncope.core.persistence.api.entity.Realm;
import org.apache.syncope.core.persistence.api.entity.group.Group;
import org.apache.syncope.core.persistence.api.entity.group.TypeExtension;
import org.apache.syncope.core.provisioning.api.data.GroupDataBinder;
@@ -55,6 +57,8 @@ import org.springframework.transaction.annotation.Transactional;
@Transactional(readOnly = true)
public class SyncopeLogic extends AbstractLogic<EntityTO> {
+ protected final RealmDAO realmDAO;
+
protected final AnyTypeDAO anyTypeDAO;
protected final GroupDAO groupDAO;
@@ -74,6 +78,7 @@ public class SyncopeLogic extends AbstractLogic<EntityTO> {
protected final AnyObjectWorkflowAdapter awfAdapter;
public SyncopeLogic(
+ final RealmDAO realmDAO,
final AnyTypeDAO anyTypeDAO,
final GroupDAO groupDAO,
final AnySearchDAO searchDAO,
@@ -84,6 +89,7 @@ public class SyncopeLogic extends AbstractLogic<EntityTO> {
final GroupWorkflowAdapter gwfAdapter,
final AnyObjectWorkflowAdapter awfAdapter) {
+ this.realmDAO = realmDAO;
this.anyTypeDAO = anyTypeDAO;
this.groupDAO = groupDAO;
this.searchDAO = searchDAO;
@@ -114,6 +120,9 @@ public class SyncopeLogic extends AbstractLogic<EntityTO> {
final int page,
final int size) {
+ Realm base = Optional.ofNullable(realmDAO.findByFullPath(realm)).
+ orElseThrow(() -> new NotFoundException("Realm " + realm));
+
AssignableCond assignableCond = new AssignableCond();
assignableCond.setRealmFullPath(realm);
@@ -137,16 +146,20 @@ public class SyncopeLogic extends AbstractLogic<EntityTO> {
searchCond = SearchCond.getLeaf(assignableCond);
}
- int count = searchDAO.count(SyncopeConstants.FULL_ADMIN_REALMS, searchCond, AnyTypeKind.GROUP);
+ int count = searchDAO.count(base, true, SyncopeConstants.FULL_ADMIN_REALMS, searchCond, AnyTypeKind.GROUP);
OrderByClause orderByClause = new OrderByClause();
orderByClause.setField("name");
orderByClause.setDirection(OrderByClause.Direction.ASC);
List<Group> matching = searchDAO.search(
+ base,
+ true,
SyncopeConstants.FULL_ADMIN_REALMS,
searchCond,
- page, size,
- List.of(orderByClause), AnyTypeKind.GROUP);
+ page,
+ size,
+ List.of(orderByClause),
+ AnyTypeKind.GROUP);
List<GroupTO> result = matching.stream().
map(group -> groupDataBinder.getGroupTO(group, false)).collect(Collectors.toList());
diff --git a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/UserLogic.java b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/UserLogic.java
index 84a53f8d2d..0e7db7416b 100644
--- a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/UserLogic.java
+++ b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/UserLogic.java
@@ -56,6 +56,7 @@ import org.apache.syncope.core.persistence.api.dao.UserDAO;
import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
import org.apache.syncope.core.persistence.api.entity.AccessToken;
+import org.apache.syncope.core.persistence.api.entity.Realm;
import org.apache.syncope.core.persistence.api.entity.group.Group;
import org.apache.syncope.core.persistence.api.entity.user.User;
import org.apache.syncope.core.provisioning.api.LogicActions;
@@ -144,16 +145,21 @@ public class UserLogic extends AbstractAnyLogic<UserTO, UserCR, UserUR> {
final SearchCond searchCond,
final int page, final int size, final List<OrderByClause> orderBy,
final String realm,
+ final boolean recursive,
final boolean details) {
+ Realm base = Optional.ofNullable(realmDAO.findByFullPath(realm)).
+ orElseThrow(() -> new NotFoundException("Realm " + realm));
+
Set<String> authRealms = RealmUtils.getEffective(
AuthContextUtils.getAuthorizations().get(IdRepoEntitlement.USER_SEARCH), realm);
SearchCond effectiveCond = searchCond == null ? userDAO.getAllMatchingCond() : searchCond;
- int count = searchDAO.count(authRealms, effectiveCond, AnyTypeKind.USER);
+ int count = searchDAO.count(base, recursive, authRealms, effectiveCond, AnyTypeKind.USER);
- List<User> matching = searchDAO.search(authRealms, effectiveCond, page, size, orderBy, AnyTypeKind.USER);
+ List<User> matching = searchDAO.search(
+ base, recursive, authRealms, effectiveCond, page, size, orderBy, AnyTypeKind.USER);
List<UserTO> result = matching.stream().
map(user -> binder.getUserTO(user, details)).
collect(Collectors.toList());
diff --git a/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AbstractAnyService.java b/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AbstractAnyService.java
index f821a81ce8..d37ab65604 100644
--- a/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AbstractAnyService.java
+++ b/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AbstractAnyService.java
@@ -144,6 +144,7 @@ public abstract class AbstractAnyService<TO extends AnyTO, CR extends AnyCR, UR
anyQuery.getSize(),
getOrderByClauses(anyQuery.getOrderBy()),
isAssignableCond ? SyncopeConstants.ROOT_REALM : realm,
+ anyQuery.getRecursive(),
anyQuery.getDetails());
return buildPagedResult(result.getRight(), anyQuery.getPage(), anyQuery.getSize(), result.getLeft());
diff --git a/core/idrepo/rest-cxf/src/test/java/org/apache/syncope/core/rest/cxf/service/AnyObjectServiceTest.java b/core/idrepo/rest-cxf/src/test/java/org/apache/syncope/core/rest/cxf/service/AnyObjectServiceTest.java
index e5213bd572..5078c55fa8 100644
--- a/core/idrepo/rest-cxf/src/test/java/org/apache/syncope/core/rest/cxf/service/AnyObjectServiceTest.java
+++ b/core/idrepo/rest-cxf/src/test/java/org/apache/syncope/core/rest/cxf/service/AnyObjectServiceTest.java
@@ -78,6 +78,7 @@ import org.apache.syncope.core.rest.cxf.RestServiceExceptionMapper;
import org.apache.syncope.common.lib.jackson.SyncopeJsonMapper;
import org.apache.syncope.common.lib.jackson.SyncopeXmlMapper;
import org.apache.syncope.common.lib.jackson.SyncopeYAMLMapper;
+import org.apache.syncope.core.persistence.api.entity.Realm;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
@@ -129,7 +130,8 @@ public class AnyObjectServiceTest {
AnyObjectDAO anyObjectDAO = mock(AnyObjectDAO.class);
AnyObjectLogic logic = mock(AnyObjectLogic.class);
- when(logic.search(any(SearchCond.class), anyInt(), anyInt(), anyList(), anyString(), anyBoolean())).
+ when(logic.search(
+ any(SearchCond.class), anyInt(), anyInt(), anyList(), anyString(), anyBoolean(), anyBoolean())).
thenAnswer(ic -> {
AnyObjectTO printer1 = new AnyObjectTO();
printer1.setKey(UUID.randomUUID().toString());
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnySearchDAO.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnySearchDAO.java
index 8d0de626a9..107932c33e 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnySearchDAO.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnySearchDAO.java
@@ -24,16 +24,24 @@ import org.apache.syncope.common.lib.types.AnyTypeKind;
import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
import org.apache.syncope.core.persistence.api.entity.Any;
+import org.apache.syncope.core.persistence.api.entity.Realm;
public interface AnySearchDAO extends DAO<Any<?>> {
/**
+ * @param base Realm to start searching from
+ * @param recursive whether search should recursively include results from child Realms
* @param adminRealms realms for which the caller owns the proper entitlement(s)
* @param searchCondition the search condition
* @param kind any object
* @return size of search result
*/
- int count(Set<String> adminRealms, SearchCond searchCondition, AnyTypeKind kind);
+ int count(
+ Realm base,
+ boolean recursive,
+ Set<String> adminRealms,
+ SearchCond searchCondition,
+ AnyTypeKind kind);
/**
* @param searchCondition the search condition
@@ -53,6 +61,8 @@ public interface AnySearchDAO extends DAO<Any<?>> {
<T extends Any<?>> List<T> search(SearchCond searchCondition, List<OrderByClause> orderBy, AnyTypeKind kind);
/**
+ * @param base Realm to start searching from
+ * @param recursive whether search should recursively include results from child Realms
* @param adminRealms realms for which the caller owns the proper entitlement(s)
* @param searchCondition the search condition
* @param page position of the first result, start from 1
@@ -63,6 +73,12 @@ public interface AnySearchDAO extends DAO<Any<?>> {
* @return the list of any objects matching the given search condition (in the given page)
*/
<T extends Any<?>> List<T> search(
- Set<String> adminRealms, SearchCond searchCondition, int page, int itemsPerPage,
- List<OrderByClause> orderBy, AnyTypeKind kind);
+ Realm base,
+ boolean recursive,
+ Set<String> adminRealms,
+ SearchCond searchCondition,
+ int page,
+ int itemsPerPage,
+ List<OrderByClause> orderBy,
+ AnyTypeKind kind);
}
diff --git a/core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/PGJPAJSONAnySearchDAO.java b/core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/PGJPAJSONAnySearchDAO.java
index eb8d631152..3a4191d766 100644
--- a/core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/PGJPAJSONAnySearchDAO.java
+++ b/core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/PGJPAJSONAnySearchDAO.java
@@ -633,12 +633,19 @@ public class PGJPAJSONAnySearchDAO extends JPAAnySearchDAO {
}
@Override
- protected int doCount(final Set<String> adminRealms, final SearchCond cond, final AnyTypeKind kind) {
+ protected int doCount(
+ final Realm base,
+ final boolean recursive,
+ final Set<String> adminRealms,
+ final SearchCond cond,
+ final AnyTypeKind kind) {
+
List<Object> parameters = new ArrayList<>();
SearchSupport svs = buildSearchSupport(kind);
- Triple<String, Set<String>, Set<String>> filter = getAdminRealmsFilter(adminRealms, svs, parameters);
+ Triple<String, Set<String>, Set<String>> filter =
+ getAdminRealmsFilter(base, recursive, adminRealms, svs, parameters);
Pair<StringBuilder, Set<String>> queryInfo =
getQuery(buildEffectiveCond(cond, filter.getMiddle(), filter.getRight(), kind), parameters, svs);
@@ -657,6 +664,8 @@ public class PGJPAJSONAnySearchDAO extends JPAAnySearchDAO {
@Override
@SuppressWarnings("unchecked")
protected <T extends Any<?>> List<T> doSearch(
+ final Realm base,
+ final boolean recursive,
final Set<String> adminRealms,
final SearchCond cond,
final int page,
@@ -669,7 +678,8 @@ public class PGJPAJSONAnySearchDAO extends JPAAnySearchDAO {
SearchSupport svs = buildSearchSupport(kind);
- Triple<String, Set<String>, Set<String>> filter = getAdminRealmsFilter(adminRealms, svs, parameters);
+ Triple<String, Set<String>, Set<String>> filter =
+ getAdminRealmsFilter(base, recursive, adminRealms, svs, parameters);
SearchCond effectiveCond = buildEffectiveCond(cond, filter.getMiddle(), filter.getRight(), kind);
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractAnySearchDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractAnySearchDAO.java
index f4bd37af97..b6679d56ba 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractAnySearchDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractAnySearchDAO.java
@@ -62,6 +62,7 @@ import org.apache.syncope.core.persistence.api.entity.PlainSchema;
import org.apache.syncope.core.persistence.api.entity.Realm;
import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
import org.apache.syncope.core.persistence.jpa.entity.JPAPlainSchema;
+import org.springframework.util.CollectionUtils;
public abstract class AbstractAnySearchDAO extends AbstractDAO<Any<?>> implements AnySearchDAO {
@@ -146,11 +147,18 @@ public abstract class AbstractAnySearchDAO extends AbstractDAO<Any<?>> implement
this.anyUtilsFactory = anyUtilsFactory;
}
- protected abstract int doCount(Set<String> adminRealms, SearchCond cond, AnyTypeKind kind);
+ protected abstract int doCount(
+ Realm base, boolean recursive, Set<String> adminRealms, SearchCond cond, AnyTypeKind kind);
@Override
- public int count(final Set<String> adminRealms, final SearchCond cond, final AnyTypeKind kind) {
- if (adminRealms == null || adminRealms.isEmpty()) {
+ public int count(
+ final Realm base,
+ final boolean recursive,
+ final Set<String> adminRealms,
+ final SearchCond cond,
+ final AnyTypeKind kind) {
+
+ if (CollectionUtils.isEmpty(adminRealms)) {
LOG.error("No realms provided");
return 0;
}
@@ -161,7 +169,7 @@ public abstract class AbstractAnySearchDAO extends AbstractDAO<Any<?>> implement
return 0;
}
- return doCount(adminRealms, cond, kind);
+ return doCount(base, recursive, adminRealms, cond, kind);
}
@Override
@@ -173,10 +181,12 @@ public abstract class AbstractAnySearchDAO extends AbstractDAO<Any<?>> implement
public <T extends Any<?>> List<T> search(
final SearchCond cond, final List<OrderByClause> orderBy, final AnyTypeKind kind) {
- return search(SyncopeConstants.FULL_ADMIN_REALMS, cond, -1, -1, orderBy, kind);
+ return search(realmDAO.getRoot(), true, SyncopeConstants.FULL_ADMIN_REALMS, cond, -1, -1, orderBy, kind);
}
protected abstract <T extends Any<?>> List<T> doSearch(
+ Realm base,
+ boolean recursive,
Set<String> adminRealms,
SearchCond searchCondition,
int page,
@@ -347,6 +357,8 @@ public abstract class AbstractAnySearchDAO extends AbstractDAO<Any<?>> implement
@Override
public <T extends Any<?>> List<T> search(
+ final Realm base,
+ final boolean recursive,
final Set<String> adminRealms,
final SearchCond cond,
final int page,
@@ -354,7 +366,7 @@ public abstract class AbstractAnySearchDAO extends AbstractDAO<Any<?>> implement
final List<OrderByClause> orderBy,
final AnyTypeKind kind) {
- if (adminRealms == null || adminRealms.isEmpty()) {
+ if (CollectionUtils.isEmpty(adminRealms)) {
LOG.error("No realms provided");
return List.of();
}
@@ -377,6 +389,6 @@ public abstract class AbstractAnySearchDAO extends AbstractDAO<Any<?>> implement
collect(Collectors.toList());
}
- return doSearch(adminRealms, cond, page, itemsPerPage, effectiveOrderBy, kind);
+ return doSearch(base, recursive, adminRealms, cond, page, itemsPerPage, effectiveOrderBy, kind);
}
}
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnySearchDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnySearchDAO.java
index 4e2ed07453..08374986bf 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnySearchDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnySearchDAO.java
@@ -100,6 +100,8 @@ public class JPAAnySearchDAO extends AbstractAnySearchDAO {
}
protected Triple<String, Set<String>, Set<String>> getAdminRealmsFilter(
+ final Realm base,
+ final boolean recursive,
final Set<String> adminRealms,
final SearchSupport svs,
final List<Object> parameters) {
@@ -108,31 +110,37 @@ public class JPAAnySearchDAO extends AbstractAnySearchDAO {
Set<String> dynRealmKeys = new HashSet<>();
Set<String> groupOwners = new HashSet<>();
- adminRealms.forEach(realmPath -> {
- Optional<Pair<String, String>> goRealm = RealmUtils.parseGroupOwnerRealm(realmPath);
- if (goRealm.isPresent()) {
- groupOwners.add(goRealm.get().getRight());
- } else if (realmPath.startsWith("/")) {
- Realm realm = realmDAO.findByFullPath(realmPath);
- if (realm == null) {
- SyncopeClientException noRealm = SyncopeClientException.build(ClientExceptionType.InvalidRealm);
- noRealm.getElements().add("Invalid realm specified: " + realmPath);
- throw noRealm;
- } else {
- realmKeys.addAll(realmDAO.findDescendants(realm).stream().
- map(Realm::getKey).collect(Collectors.toSet()));
- }
- } else {
- DynRealm dynRealm = dynRealmDAO.find(realmPath);
- if (dynRealm == null) {
- LOG.warn("Ignoring invalid dynamic realm {}", realmPath);
+ if (recursive) {
+ adminRealms.forEach(realmPath -> {
+ Optional<Pair<String, String>> goRealm = RealmUtils.parseGroupOwnerRealm(realmPath);
+ if (goRealm.isPresent()) {
+ groupOwners.add(goRealm.get().getRight());
+ } else if (realmPath.startsWith("/")) {
+ Realm realm = realmDAO.findByFullPath(realmPath);
+ if (realm == null) {
+ SyncopeClientException noRealm = SyncopeClientException.build(ClientExceptionType.InvalidRealm);
+ noRealm.getElements().add("Invalid realm specified: " + realmPath);
+ throw noRealm;
+ } else {
+ realmKeys.addAll(realmDAO.findDescendants(realm).stream().
+ map(Realm::getKey).collect(Collectors.toSet()));
+ }
} else {
- dynRealmKeys.add(dynRealm.getKey());
+ DynRealm dynRealm = dynRealmDAO.find(realmPath);
+ if (dynRealm == null) {
+ LOG.warn("Ignoring invalid dynamic realm {}", realmPath);
+ } else {
+ dynRealmKeys.add(dynRealm.getKey());
+ }
}
+ });
+ if (!dynRealmKeys.isEmpty()) {
+ realmKeys.clear();
+ }
+ } else {
+ if (adminRealms.stream().anyMatch(r -> base.getFullPath().startsWith(r))) {
+ realmKeys.add(base.getKey());
}
- });
- if (!dynRealmKeys.isEmpty()) {
- realmKeys.clear();
}
return Triple.of(buildAdminRealmsFilter(realmKeys, svs, parameters), dynRealmKeys, groupOwners);
@@ -143,12 +151,19 @@ public class JPAAnySearchDAO extends AbstractAnySearchDAO {
}
@Override
- protected int doCount(final Set<String> adminRealms, final SearchCond cond, final AnyTypeKind kind) {
+ protected int doCount(
+ final Realm base,
+ final boolean recursive,
+ final Set<String> adminRealms,
+ final SearchCond cond,
+ final AnyTypeKind kind) {
+
List<Object> parameters = new ArrayList<>();
SearchSupport svs = buildSearchSupport(kind);
- Triple<String, Set<String>, Set<String>> filter = getAdminRealmsFilter(adminRealms, svs, parameters);
+ Triple<String, Set<String>, Set<String>> filter =
+ getAdminRealmsFilter(base, recursive, adminRealms, svs, parameters);
// 1. get the query string from the search condition
Pair<StringBuilder, Set<String>> queryInfo =
@@ -156,7 +171,7 @@ public class JPAAnySearchDAO extends AbstractAnySearchDAO {
StringBuilder queryString = queryInfo.getLeft();
- // 2. take into account administrative realms
+ // 2. take realms into account
queryString.insert(0, "SELECT u.any_id FROM (");
queryString.append(") u WHERE ").append(filter.getLeft());
@@ -173,6 +188,8 @@ public class JPAAnySearchDAO extends AbstractAnySearchDAO {
@Override
@SuppressWarnings("unchecked")
protected <T extends Any<?>> List<T> doSearch(
+ final Realm base,
+ final boolean recursive,
final Set<String> adminRealms,
final SearchCond cond,
final int page,
@@ -185,7 +202,8 @@ public class JPAAnySearchDAO extends AbstractAnySearchDAO {
SearchSupport svs = buildSearchSupport(kind);
- Triple<String, Set<String>, Set<String>> filter = getAdminRealmsFilter(adminRealms, svs, parameters);
+ Triple<String, Set<String>, Set<String>> filter =
+ getAdminRealmsFilter(base, recursive, adminRealms, svs, parameters);
// 1. get the query string from the search condition
Pair<StringBuilder, Set<String>> queryInfo =
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 df071e5a70..45c13aa958 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
@@ -297,9 +297,12 @@ public class JPAGroupDAO extends AbstractAnyDAO<Group> implements GroupDAO {
clearUDynMembers(merged);
if (merged.getUDynMembership() != null) {
SearchCond cond = buildDynMembershipCond(merged.getUDynMembership().getFIQLCond(), merged.getRealm());
- int count = anySearchDAO.count(Set.of(merged.getRealm().getFullPath()), cond, AnyTypeKind.USER);
+ int count = anySearchDAO.count(
+ merged.getRealm(), true, Set.of(merged.getRealm().getFullPath()), cond, AnyTypeKind.USER);
for (int page = 1; page <= (count / AnyDAO.DEFAULT_PAGE_SIZE) + 1; page++) {
List<User> matching = anySearchDAO.search(
+ merged.getRealm(),
+ true,
Set.of(merged.getRealm().getFullPath()),
cond,
page,
@@ -321,9 +324,12 @@ public class JPAGroupDAO extends AbstractAnyDAO<Group> implements GroupDAO {
clearADynMembers(merged);
merged.getADynMemberships().forEach(memb -> {
SearchCond cond = buildDynMembershipCond(memb.getFIQLCond(), merged.getRealm());
- int count = anySearchDAO.count(Set.of(merged.getRealm().getFullPath()), cond, AnyTypeKind.ANY_OBJECT);
+ int count = anySearchDAO.count(
+ merged.getRealm(), true, Set.of(merged.getRealm().getFullPath()), cond, AnyTypeKind.ANY_OBJECT);
for (int page = 1; page <= (count / AnyDAO.DEFAULT_PAGE_SIZE) + 1; page++) {
List<AnyObject> matching = anySearchDAO.search(
+ merged.getRealm(),
+ true,
Set.of(merged.getRealm().getFullPath()),
cond,
page,
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/AnySearchTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/AnySearchTest.java
index 11df808b1e..e4dad5d2f4 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/AnySearchTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/AnySearchTest.java
@@ -274,16 +274,17 @@ public class AnySearchTest extends AbstractTest {
assertTrue(cond.isValid());
- int count = searchDAO.count(SyncopeConstants.FULL_ADMIN_REALMS, cond, AnyTypeKind.USER);
+ int count = searchDAO.count(
+ realmDAO.getRoot(), true, SyncopeConstants.FULL_ADMIN_REALMS, cond, AnyTypeKind.USER);
assertEquals(1, count);
- List<User> users = searchDAO.search(SyncopeConstants.FULL_ADMIN_REALMS,
- cond, 1, 2, List.of(), AnyTypeKind.USER);
+ List<User> users = searchDAO.search(
+ realmDAO.getRoot(), true, SyncopeConstants.FULL_ADMIN_REALMS, cond, 1, 2, List.of(), AnyTypeKind.USER);
assertNotNull(users);
assertEquals(1, users.size());
- users = searchDAO.search(SyncopeConstants.FULL_ADMIN_REALMS,
- cond, 2, 2, List.of(), AnyTypeKind.USER);
+ users = searchDAO.search(
+ realmDAO.getRoot(), true, SyncopeConstants.FULL_ADMIN_REALMS, cond, 2, 2, List.of(), AnyTypeKind.USER);
assertNotNull(users);
assertTrue(users.isEmpty());
}
@@ -315,6 +316,12 @@ public class AnySearchTest extends AbstractTest {
assertTrue(matchingStar.stream().anyMatch(user -> "verdi".equals(user.getUsername())));
assertTrue(matchingStar.stream().anyMatch(user -> "rossini".equals(user.getUsername())));
assertEquals(union, matchingStar.stream().map(User::getUsername).collect(Collectors.toSet()));
+
+ matchingStar = searchDAO.search(realmDAO.getRoot(), false, SyncopeConstants.FULL_ADMIN_REALMS,
+ SearchCond.getLeaf(groupCond), -1, -1, List.of(), AnyTypeKind.USER);
+ assertNotNull(matchingStar);
+ assertTrue(matchingStar.stream().anyMatch(user -> "verdi".equals(user.getUsername())));
+ assertTrue(matchingStar.stream().noneMatch(user -> "rossini".equals(user.getUsername())));
}
@Test
@@ -439,8 +446,7 @@ public class AnySearchTest extends AbstractTest {
SearchCond.getLeaf(usernameLeafCond),
SearchCond.getLeaf(idRightCond));
- List<User> matchingUsers = searchDAO.search(
- searchCondition, AnyTypeKind.USER);
+ List<User> matchingUsers = searchDAO.search(searchCondition, AnyTypeKind.USER);
assertNotNull(matchingUsers);
assertEquals(2, matchingUsers.size());
}
@@ -459,8 +465,7 @@ public class AnySearchTest extends AbstractTest {
SearchCond.getLeaf(usernameLeafCond),
SearchCond.getLeaf(idRightCond));
- List<User> matchingUsers = searchDAO.search(
- searchCondition, AnyTypeKind.USER);
+ List<User> matchingUsers = searchDAO.search(searchCondition, AnyTypeKind.USER);
assertNotNull(matchingUsers);
assertEquals(2, matchingUsers.size());
}
@@ -578,7 +583,9 @@ public class AnySearchTest extends AbstractTest {
List<User> users = searchDAO.search(searchCondition, orderByClauses, AnyTypeKind.USER);
assertEquals(
- searchDAO.count(SyncopeConstants.FULL_ADMIN_REALMS, searchCondition, AnyTypeKind.USER),
+ searchDAO.count(
+ realmDAO.getRoot(), true,
+ SyncopeConstants.FULL_ADMIN_REALMS, searchCondition, AnyTypeKind.USER),
users.size());
}
@@ -596,7 +603,9 @@ public class AnySearchTest extends AbstractTest {
List<Group> groups = searchDAO.search(
searchCondition, List.of(orderByClause), AnyTypeKind.GROUP);
assertEquals(
- searchDAO.count(SyncopeConstants.FULL_ADMIN_REALMS, searchCondition, AnyTypeKind.GROUP),
+ searchDAO.count(
+ realmDAO.getRoot(), true,
+ SyncopeConstants.FULL_ADMIN_REALMS, searchCondition, AnyTypeKind.GROUP),
groups.size());
}
@@ -668,10 +677,20 @@ public class AnySearchTest extends AbstractTest {
AuthContextUtils.getAuthorizations().get(IdRepoEntitlement.GROUP_SEARCH),
SyncopeConstants.ROOT_REALM);
- assertEquals(1, searchDAO.count(authRealms, groupDAO.getAllMatchingCond(), AnyTypeKind.GROUP));
+ assertEquals(
+ 1,
+ searchDAO.count(
+ realmDAO.getRoot(), true, authRealms, groupDAO.getAllMatchingCond(), AnyTypeKind.GROUP));
List<Group> groups = searchDAO.search(
- authRealms, groupDAO.getAllMatchingCond(), 1, 10, List.of(), AnyTypeKind.GROUP);
+ realmDAO.getRoot(),
+ true,
+ authRealms,
+ groupDAO.getAllMatchingCond(),
+ 1,
+ 10,
+ List.of(),
+ AnyTypeKind.GROUP);
assertEquals(1, groups.size());
assertEquals("37d15e4c-cdc1-460b-a591-8505c8133806", groups.get(0).getKey());
} finally {
@@ -737,8 +756,8 @@ public class AnySearchTest extends AbstractTest {
SearchCond searchCond = SearchCond.getOr(
SearchCond.getLeaf(isNullCond), SearchCond.getLeaf(likeCond));
- Integer count = searchDAO.count(SyncopeConstants.FULL_ADMIN_REALMS, searchCond, AnyTypeKind.USER);
- assertNotNull(count);
+ int count = searchDAO.count(
+ realmDAO.getRoot(), true, SyncopeConstants.FULL_ADMIN_REALMS, searchCond, AnyTypeKind.USER);
assertTrue(count > 0);
}
@@ -752,16 +771,13 @@ public class AnySearchTest extends AbstractTest {
genderCond.setSchema("gender");
genderCond.setExpression("M");
- SearchCond orCond =
- SearchCond.getOr(SearchCond.getLeaf(rossiniCond),
- SearchCond.getLeaf(genderCond));
+ SearchCond orCond = SearchCond.getOr(SearchCond.getLeaf(rossiniCond), SearchCond.getLeaf(genderCond));
AttrCond belliniCond = new AttrCond(AttrCond.Type.EQ);
belliniCond.setSchema("surname");
belliniCond.setExpression("Bellini");
- SearchCond searchCond =
- SearchCond.getAnd(orCond, SearchCond.getLeaf(belliniCond));
+ SearchCond searchCond = SearchCond.getAnd(orCond, SearchCond.getLeaf(belliniCond));
List<User> users = searchDAO.search(searchCond, AnyTypeKind.USER);
assertNotNull(users);
@@ -810,8 +826,7 @@ public class AnySearchTest extends AbstractTest {
AnyTypeCond anyTypeCond = new AnyTypeCond();
anyTypeCond.setAnyTypeKey(service.getKey());
- searchCondition = SearchCond.getAnd(
- SearchCond.getLeaf(groupCond), SearchCond.getLeaf(anyTypeCond));
+ searchCondition = SearchCond.getAnd(SearchCond.getLeaf(groupCond), SearchCond.getLeaf(anyTypeCond));
matching = searchDAO.search(searchCondition, AnyTypeKind.ANY_OBJECT);
assertEquals(1, matching.size());
@@ -834,6 +849,8 @@ public class AnySearchTest extends AbstractTest {
orderByClauses.add(orderByClause);
List<User> users = searchDAO.search(
+ realmDAO.getRoot(),
+ true,
SyncopeConstants.FULL_ADMIN_REALMS,
SearchCond.getLeaf(fullnameLeafCond),
-1,
@@ -851,8 +868,7 @@ public class AnySearchTest extends AbstractTest {
AttrCond idRightCond = new AttrCond(AttrCond.Type.ISNOTNULL);
idRightCond.setSchema("firstname");
- SearchCond searchCondition = SearchCond.getAnd(
- SearchCond.getLeaf(idLeftCond), SearchCond.getLeaf(idRightCond));
+ SearchCond searchCondition = SearchCond.getAnd(SearchCond.getLeaf(idLeftCond), SearchCond.getLeaf(idRightCond));
List<OrderByClause> orderByClauses = new ArrayList<>();
OrderByClause orderByClause = new OrderByClause();
@@ -861,8 +877,8 @@ public class AnySearchTest extends AbstractTest {
orderByClauses.add(orderByClause);
List<User> users = searchDAO.search(searchCondition, orderByClauses, AnyTypeKind.USER);
- assertEquals(
- searchDAO.count(SyncopeConstants.FULL_ADMIN_REALMS, searchCondition, AnyTypeKind.USER),
+ assertEquals(searchDAO.count(
+ realmDAO.getRoot(), true, SyncopeConstants.FULL_ADMIN_REALMS, searchCondition, AnyTypeKind.USER),
users.size());
// search by attribute with unique constraint
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/AnySearchTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/AnySearchTest.java
index b371889e7f..051ba5588b 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/AnySearchTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/AnySearchTest.java
@@ -26,6 +26,7 @@ import static org.junit.jupiter.api.Assertions.fail;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Set;
import org.apache.syncope.common.lib.SyncopeClientException;
import org.apache.syncope.common.lib.SyncopeConstants;
import org.apache.syncope.common.lib.types.AnyTypeKind;
@@ -130,14 +131,16 @@ public class AnySearchTest extends AbstractTest {
anyCond.setSchema("id");
List<User> users = searchDAO.search(
- Collections.singleton(SyncopeConstants.ROOT_REALM),
+ realmDAO.getRoot(), true,
+ Set.of(SyncopeConstants.ROOT_REALM),
SearchCond.getLeaf(anyCond), 1, 100, Collections.emptyList(), AnyTypeKind.USER);
assertNotNull(users);
assertTrue(users.stream().anyMatch(user -> rossini.getKey().equals(user.getKey())));
// 3. search all users with director owner's entitlements: only rossini is returned
users = searchDAO.search(
- Collections.singleton(RealmUtils.getGroupOwnerRealm(group.getRealm().getFullPath(), group.getKey())),
+ group.getRealm(), true,
+ Set.of(RealmUtils.getGroupOwnerRealm(group.getRealm().getFullPath(), group.getKey())),
SearchCond.getLeaf(anyCond), 1, 100, Collections.emptyList(), AnyTypeKind.USER);
assertNotNull(users);
assertEquals(1, users.size());
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/report/GroupReportlet.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/report/GroupReportlet.java
index 55db10701f..29fb7347ca 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/report/GroupReportlet.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/report/GroupReportlet.java
@@ -37,6 +37,7 @@ import org.apache.syncope.core.persistence.api.dao.GroupDAO;
import org.apache.syncope.core.persistence.api.entity.group.Group;
import org.apache.syncope.core.persistence.api.search.SearchCondConverter;
import org.apache.syncope.core.persistence.api.dao.AnySearchDAO;
+import org.apache.syncope.core.persistence.api.dao.RealmDAO;
import org.apache.syncope.core.persistence.api.dao.ReportletConfClass;
import org.apache.syncope.core.persistence.api.entity.user.UMembership;
import org.apache.syncope.core.persistence.api.search.SearchCondVisitor;
@@ -50,20 +51,23 @@ import org.xml.sax.helpers.AttributesImpl;
public class GroupReportlet extends AbstractReportlet {
@Autowired
- private GroupDAO groupDAO;
+ protected RealmDAO realmDAO;
@Autowired
- private AnySearchDAO searchDAO;
+ protected GroupDAO groupDAO;
@Autowired
- private GroupDataBinder groupDataBinder;
+ protected AnySearchDAO searchDAO;
@Autowired
- private SearchCondVisitor searchCondVisitor;
+ protected GroupDataBinder groupDataBinder;
- private GroupReportletConf conf;
+ @Autowired
+ protected SearchCondVisitor searchCondVisitor;
+
+ protected GroupReportletConf conf;
- private static void doExtractResources(final ContentHandler handler, final AnyTO anyTO)
+ protected void doExtractResources(final ContentHandler handler, final AnyTO anyTO)
throws SAXException {
if (anyTO.getResources().isEmpty()) {
@@ -84,9 +88,12 @@ public class GroupReportlet extends AbstractReportlet {
}
}
- private static void doExtractAttributes(final ContentHandler handler, final AnyTO anyTO,
- final Collection<String> attrs, final Collection<String> derAttrs,
- final Collection<String> virAttrs)
+ protected void doExtractAttributes(
+ final ContentHandler handler,
+ final AnyTO anyTO,
+ final Collection<String> attrs,
+ final Collection<String> derAttrs,
+ final Collection<String> virAttrs)
throws SAXException {
AttributesImpl atts = new AttributesImpl();
@@ -169,7 +176,7 @@ public class GroupReportlet extends AbstractReportlet {
}
}
- private void doExtract(final ContentHandler handler, final List<Group> groups) throws SAXException {
+ protected void doExtract(final ContentHandler handler, final List<Group> groups) throws SAXException {
AttributesImpl atts = new AttributesImpl();
for (Group group : groups) {
atts.clear();
@@ -241,7 +248,7 @@ public class GroupReportlet extends AbstractReportlet {
}
}
- private void doExtractConf(final ContentHandler handler) throws SAXException {
+ protected void doExtractConf(final ContentHandler handler) throws SAXException {
if (conf == null) {
LOG.debug("Report configuration is not present");
}
@@ -284,11 +291,15 @@ public class GroupReportlet extends AbstractReportlet {
handler.endElement("", "", "configurations");
}
- private int count() {
+ protected int count() {
return StringUtils.isBlank(conf.getMatchingCond())
? groupDAO.count()
- : searchDAO.count(SyncopeConstants.FULL_ADMIN_REALMS,
- SearchCondConverter.convert(searchCondVisitor, conf.getMatchingCond()), AnyTypeKind.GROUP);
+ : searchDAO.count(
+ realmDAO.getRoot(),
+ true,
+ SyncopeConstants.FULL_ADMIN_REALMS,
+ SearchCondConverter.convert(searchCondVisitor, conf.getMatchingCond()),
+ AnyTypeKind.GROUP);
}
@Override
@@ -319,6 +330,8 @@ public class GroupReportlet extends AbstractReportlet {
groups = groupDAO.findAll(page, AnyDAO.DEFAULT_PAGE_SIZE);
} else {
groups = searchDAO.search(
+ realmDAO.getRoot(),
+ true,
SyncopeConstants.FULL_ADMIN_REALMS,
SearchCondConverter.convert(searchCondVisitor, this.conf.getMatchingCond()),
page,
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/report/ReconciliationReportlet.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/report/ReconciliationReportlet.java
index cc386a5d39..026cfbf1de 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/report/ReconciliationReportlet.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/report/ReconciliationReportlet.java
@@ -40,6 +40,7 @@ import org.apache.syncope.core.provisioning.api.utils.FormatUtils;
import org.apache.syncope.core.persistence.api.dao.AnySearchDAO;
import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
import org.apache.syncope.core.persistence.api.dao.GroupDAO;
+import org.apache.syncope.core.persistence.api.dao.RealmDAO;
import org.apache.syncope.core.persistence.api.dao.ReportletConfClass;
import org.apache.syncope.core.persistence.api.dao.UserDAO;
import org.apache.syncope.core.persistence.api.dao.search.AnyTypeCond;
@@ -76,6 +77,9 @@ public class ReconciliationReportlet extends AbstractReportlet {
private static final int PAGE_SIZE = 10;
+ @Autowired
+ private RealmDAO realmDAO;
+
@Autowired
private UserDAO userDAO;
@@ -388,7 +392,12 @@ public class ReconciliationReportlet extends AbstractReportlet {
} else {
SearchCond cond = SearchCondConverter.convert(searchCondVisitor, this.conf.getUserMatchingCond());
- int total = searchDAO.count(SyncopeConstants.FULL_ADMIN_REALMS, cond, AnyTypeKind.USER);
+ int total = searchDAO.count(
+ realmDAO.getRoot(),
+ true,
+ SyncopeConstants.FULL_ADMIN_REALMS,
+ cond,
+ AnyTypeKind.USER);
int pages = (total / AnyDAO.DEFAULT_PAGE_SIZE) + 1;
status.set("Processing " + total + " users in " + pages + " pages");
@@ -400,6 +409,8 @@ public class ReconciliationReportlet extends AbstractReportlet {
status.set("Processing " + total + " users: page " + page + " of " + pages);
doExtract(handler, searchDAO.search(
+ realmDAO.getRoot(),
+ true,
SyncopeConstants.FULL_ADMIN_REALMS,
cond,
page,
@@ -428,7 +439,12 @@ public class ReconciliationReportlet extends AbstractReportlet {
} else {
SearchCond cond = SearchCondConverter.convert(searchCondVisitor, this.conf.getUserMatchingCond());
- int total = searchDAO.count(SyncopeConstants.FULL_ADMIN_REALMS, cond, AnyTypeKind.GROUP);
+ int total = searchDAO.count(
+ realmDAO.getRoot(),
+ true,
+ SyncopeConstants.FULL_ADMIN_REALMS,
+ cond,
+ AnyTypeKind.GROUP);
int pages = (total / AnyDAO.DEFAULT_PAGE_SIZE) + 1;
status.set("Processing " + total + " groups in " + pages + " pages");
@@ -440,6 +456,8 @@ public class ReconciliationReportlet extends AbstractReportlet {
status.set("Processing " + total + " groups: page " + page + " of " + pages);
doExtract(handler, searchDAO.search(
+ realmDAO.getRoot(),
+ true,
SyncopeConstants.FULL_ADMIN_REALMS,
cond,
page,
@@ -460,7 +478,12 @@ public class ReconciliationReportlet extends AbstractReportlet {
SearchCond.getLeaf(anyTypeCond),
SearchCondConverter.convert(searchCondVisitor, this.conf.getAnyObjectMatchingCond()));
- int total = searchDAO.count(SyncopeConstants.FULL_ADMIN_REALMS, cond, AnyTypeKind.ANY_OBJECT);
+ int total = searchDAO.count(
+ realmDAO.getRoot(),
+ true,
+ SyncopeConstants.FULL_ADMIN_REALMS,
+ cond,
+ AnyTypeKind.ANY_OBJECT);
int pages = (total / AnyDAO.DEFAULT_PAGE_SIZE) + 1;
status.set("Processing " + total + " any objects " + anyType.getKey() + " in " + pages + " pages");
@@ -475,6 +498,8 @@ public class ReconciliationReportlet extends AbstractReportlet {
+ ": page " + page + " of " + pages);
doExtract(handler, searchDAO.search(
+ realmDAO.getRoot(),
+ true,
SyncopeConstants.FULL_ADMIN_REALMS,
cond,
page,
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/report/UserReportlet.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/report/UserReportlet.java
index 7b5c1cddf9..e4f24b5ac0 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/report/UserReportlet.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/report/UserReportlet.java
@@ -40,6 +40,7 @@ import org.apache.syncope.core.persistence.api.entity.user.User;
import org.apache.syncope.core.persistence.api.search.SearchCondConverter;
import org.apache.syncope.core.provisioning.api.utils.FormatUtils;
import org.apache.syncope.core.persistence.api.dao.AnySearchDAO;
+import org.apache.syncope.core.persistence.api.dao.RealmDAO;
import org.apache.syncope.core.persistence.api.dao.ReportletConfClass;
import org.apache.syncope.core.persistence.api.entity.user.UMembership;
import org.apache.syncope.core.persistence.api.entity.user.URelationship;
@@ -56,26 +57,29 @@ import org.xml.sax.helpers.AttributesImpl;
public class UserReportlet extends AbstractReportlet {
@Autowired
- private UserDAO userDAO;
+ protected RealmDAO realmDAO;
@Autowired
- private AnySearchDAO searchDAO;
+ protected UserDAO userDAO;
@Autowired
- private UserDataBinder userDataBinder;
+ protected AnySearchDAO searchDAO;
@Autowired
- private GroupDataBinder groupDataBinder;
+ protected UserDataBinder userDataBinder;
@Autowired
- private AnyObjectDataBinder anyObjectDataBinder;
+ protected GroupDataBinder groupDataBinder;
@Autowired
- private SearchCondVisitor searchCondVisitor;
+ protected AnyObjectDataBinder anyObjectDataBinder;
- private UserReportletConf conf;
+ @Autowired
+ protected SearchCondVisitor searchCondVisitor;
+
+ protected UserReportletConf conf;
- private static void doExtractResources(final ContentHandler handler, final AnyTO anyTO)
+ protected void doExtractResources(final ContentHandler handler, final AnyTO anyTO)
throws SAXException {
if (anyTO.getResources().isEmpty()) {
@@ -96,9 +100,12 @@ public class UserReportlet extends AbstractReportlet {
}
}
- private static void doExtractAttributes(final ContentHandler handler, final AnyTO anyTO,
- final Collection<String> attrs, final Collection<String> derAttrs,
- final Collection<String> virAttrs) throws SAXException {
+ protected void doExtractAttributes(
+ final ContentHandler handler,
+ final AnyTO anyTO,
+ final Collection<String> attrs,
+ final Collection<String> derAttrs,
+ final Collection<String> virAttrs) throws SAXException {
AttributesImpl atts = new AttributesImpl();
if (!attrs.isEmpty()) {
@@ -180,7 +187,7 @@ public class UserReportlet extends AbstractReportlet {
}
}
- private void doExtract(final ContentHandler handler, final List<User> users) throws SAXException {
+ protected void doExtract(final ContentHandler handler, final List<User> users) throws SAXException {
AttributesImpl atts = new AttributesImpl();
for (User user : users) {
atts.clear();
@@ -308,7 +315,7 @@ public class UserReportlet extends AbstractReportlet {
}
}
- private void doExtractConf(final ContentHandler handler) throws SAXException {
+ protected void doExtractConf(final ContentHandler handler) throws SAXException {
AttributesImpl atts = new AttributesImpl();
handler.startElement("", "", "configurations", null);
handler.startElement("", "", "userAttributes", atts);
@@ -345,11 +352,15 @@ public class UserReportlet extends AbstractReportlet {
handler.endElement("", "", "configurations");
}
- private int count() {
+ protected int count() {
return StringUtils.isBlank(conf.getMatchingCond())
? userDAO.count()
- : searchDAO.count(SyncopeConstants.FULL_ADMIN_REALMS,
- SearchCondConverter.convert(searchCondVisitor, this.conf.getMatchingCond()), AnyTypeKind.USER);
+ : searchDAO.count(
+ realmDAO.getRoot(),
+ true,
+ SyncopeConstants.FULL_ADMIN_REALMS,
+ SearchCondConverter.convert(searchCondVisitor, conf.getMatchingCond()),
+ AnyTypeKind.USER);
}
@Override
@@ -380,6 +391,8 @@ public class UserReportlet extends AbstractReportlet {
users = userDAO.findAll(page, AnyDAO.DEFAULT_PAGE_SIZE);
} else {
users = searchDAO.search(
+ realmDAO.getRoot(),
+ true,
SyncopeConstants.FULL_ADMIN_REALMS,
SearchCondConverter.convert(searchCondVisitor, this.conf.getMatchingCond()),
page,
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DefaultRealmPullResultHandler.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DefaultRealmPullResultHandler.java
index 6d26d10f8c..c2d0931f63 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DefaultRealmPullResultHandler.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DefaultRealmPullResultHandler.java
@@ -558,9 +558,12 @@ public class DefaultRealmPullResultHandler
AnyCond keyCond = new AnyCond(AttrCond.Type.ISNOTNULL);
keyCond.setSchema("key");
SearchCond allMatchingCond = SearchCond.getLeaf(keyCond);
- int users = searchDAO.count(adminRealms, allMatchingCond, AnyTypeKind.USER);
- int groups = searchDAO.count(adminRealms, allMatchingCond, AnyTypeKind.GROUP);
- int anyObjects = searchDAO.count(adminRealms, allMatchingCond, AnyTypeKind.ANY_OBJECT);
+ int users = searchDAO.count(
+ realmDAO.getRoot(), true, adminRealms, allMatchingCond, AnyTypeKind.USER);
+ int groups = searchDAO.count(
+ realmDAO.getRoot(), true, adminRealms, allMatchingCond, AnyTypeKind.GROUP);
+ int anyObjects = searchDAO.count(
+ realmDAO.getRoot(), true, adminRealms, allMatchingCond, AnyTypeKind.ANY_OBJECT);
if (users + groups + anyObjects > 0) {
SyncopeClientException containedAnys = SyncopeClientException.build(
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PushJobDelegate.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PushJobDelegate.java
index 1b0c3a0dae..333c482381 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PushJobDelegate.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PushJobDelegate.java
@@ -246,11 +246,15 @@ public class PushJobDelegate extends AbstractProvisioningJobDelegate<PushTask> {
? anyDAO.getAllMatchingCond()
: SearchCondConverter.convert(searchCondVisitor, filter);
int count = searchDAO.count(
+ profile.getTask().getSourceRealm(),
+ true,
Set.of(profile.getTask().getSourceRealm().getFullPath()),
cond,
provision.getAnyType().getKind());
for (int page = 1; page <= (count / AnyDAO.DEFAULT_PAGE_SIZE) + 1 && !interrupt; page++) {
List<? extends Any<?>> anys = searchDAO.search(
+ profile.getTask().getSourceRealm(),
+ true,
Set.of(profile.getTask().getSourceRealm().getFullPath()),
cond,
page,
diff --git a/ext/elasticsearch/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/ElasticsearchAnySearchDAO.java b/ext/elasticsearch/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/ElasticsearchAnySearchDAO.java
index 56d180abad..ad7dd141b3 100644
--- a/ext/elasticsearch/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/ElasticsearchAnySearchDAO.java
+++ b/ext/elasticsearch/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/ElasticsearchAnySearchDAO.java
@@ -124,40 +124,51 @@ public class ElasticsearchAnySearchDAO extends AbstractAnySearchDAO {
}
protected Triple<Optional<Query>, Set<String>, Set<String>> getAdminRealmsFilter(
- final AnyTypeKind kind, final Set<String> adminRealms) {
+ final Realm base,
+ final boolean recursive,
+ final Set<String> adminRealms,
+ final AnyTypeKind kind) {
Set<String> dynRealmKeys = new HashSet<>();
Set<String> groupOwners = new HashSet<>();
List<Query> queries = new ArrayList<>();
- adminRealms.forEach(realmPath -> {
- Optional<Pair<String, String>> goRealm = RealmUtils.parseGroupOwnerRealm(realmPath);
- if (goRealm.isPresent()) {
- groupOwners.add(goRealm.get().getRight());
- } else if (realmPath.startsWith("/")) {
- Realm realm = realmDAO.findByFullPath(realmPath);
- if (realm == null) {
- SyncopeClientException noRealm = SyncopeClientException.build(ClientExceptionType.InvalidRealm);
- noRealm.getElements().add("Invalid realm specified: " + realmPath);
- throw noRealm;
- } else {
- realmDAO.findDescendants(realm).forEach(descendant -> queries.add(
- new Query.Builder().term(QueryBuilders.term().
- field("realm").value(FieldValue.of(descendant.getFullPath())).build()).
- build()));
- }
- } else {
- DynRealm dynRealm = dynRealmDAO.find(realmPath);
- if (dynRealm == null) {
- LOG.warn("Ignoring invalid dynamic realm {}", realmPath);
+ if (recursive) {
+ adminRealms.forEach(realmPath -> {
+ Optional<Pair<String, String>> goRealm = RealmUtils.parseGroupOwnerRealm(realmPath);
+ if (goRealm.isPresent()) {
+ groupOwners.add(goRealm.get().getRight());
+ } else if (realmPath.startsWith("/")) {
+ Realm realm = realmDAO.findByFullPath(realmPath);
+ if (realm == null) {
+ SyncopeClientException noRealm = SyncopeClientException.build(ClientExceptionType.InvalidRealm);
+ noRealm.getElements().add("Invalid realm specified: " + realmPath);
+ throw noRealm;
+ } else {
+ realmDAO.findDescendants(realm).forEach(descendant -> queries.add(
+ new Query.Builder().term(QueryBuilders.term().
+ field("realm").value(FieldValue.of(descendant.getFullPath())).build()).
+ build()));
+ }
} else {
- dynRealmKeys.add(dynRealm.getKey());
- queries.add(new Query.Builder().term(QueryBuilders.term().
- field("dynRealm").value(FieldValue.of(dynRealm.getKey())).build()).
- build());
+ DynRealm dynRealm = dynRealmDAO.find(realmPath);
+ if (dynRealm == null) {
+ LOG.warn("Ignoring invalid dynamic realm {}", realmPath);
+ } else {
+ dynRealmKeys.add(dynRealm.getKey());
+ queries.add(new Query.Builder().term(QueryBuilders.term().
+ field("dynRealm").value(FieldValue.of(dynRealm.getKey())).build()).
+ build());
+ }
}
+ });
+ } else {
+ if (adminRealms.stream().anyMatch(r -> base.getFullPath().startsWith(r))) {
+ queries.add(new Query.Builder().term(QueryBuilders.term().
+ field("realm").value(FieldValue.of(base.getFullPath())).build()).
+ build());
}
- });
+ }
return Triple.of(
dynRealmKeys.isEmpty() && groupOwners.isEmpty()
@@ -168,15 +179,28 @@ public class ElasticsearchAnySearchDAO extends AbstractAnySearchDAO {
}
protected Query getQuery(
+ final Realm base,
+ final boolean recursive,
final Set<String> adminRealms,
final SearchCond cond,
final AnyTypeKind kind) {
- Triple<Optional<Query>, Set<String>, Set<String>> filter = getAdminRealmsFilter(kind, adminRealms);
Query query;
if (SyncopeConstants.FULL_ADMIN_REALMS.equals(adminRealms)) {
query = getQuery(cond, kind);
+
+ if (!recursive) {
+ query = new Query.Builder().bool(
+ QueryBuilders.bool().
+ must(new Query.Builder().term(QueryBuilders.term().
+ field("realm").value(FieldValue.of(base.getFullPath())).build()).
+ build()).
+ must(query).build()).
+ build();
+ }
} else {
+ Triple<Optional<Query>, Set<String>, Set<String>> filter =
+ getAdminRealmsFilter(base, recursive, adminRealms, kind);
query = getQuery(buildEffectiveCond(cond, filter.getMiddle(), filter.getRight(), kind), kind);
if (filter.getLeft().isPresent()) {
@@ -192,10 +216,16 @@ public class ElasticsearchAnySearchDAO extends AbstractAnySearchDAO {
}
@Override
- protected int doCount(final Set<String> adminRealms, final SearchCond cond, final AnyTypeKind kind) {
+ protected int doCount(
+ final Realm base,
+ final boolean recursive,
+ final Set<String> adminRealms,
+ final SearchCond cond,
+ final AnyTypeKind kind) {
+
CountRequest request = new CountRequest.Builder().
index(ElasticsearchUtils.getContextDomainName(AuthContextUtils.getDomain(), kind)).
- query(getQuery(adminRealms, cond, kind)).
+ query(getQuery(base, recursive, adminRealms, cond, kind)).
build();
try {
return (int) client.count(request).count();
@@ -245,6 +275,8 @@ public class ElasticsearchAnySearchDAO extends AbstractAnySearchDAO {
@Override
protected <T extends Any<?>> List<T> doSearch(
+ final Realm base,
+ final boolean recursive,
final Set<String> adminRealms,
final SearchCond cond,
final int page,
@@ -255,7 +287,7 @@ public class ElasticsearchAnySearchDAO extends AbstractAnySearchDAO {
SearchRequest request = new SearchRequest.Builder().
index(ElasticsearchUtils.getContextDomainName(AuthContextUtils.getDomain(), kind)).
searchType(SearchType.QueryThenFetch).
- query(getQuery(adminRealms, cond, kind)).
+ query(getQuery(base, recursive, adminRealms, cond, kind)).
from(itemsPerPage * (page <= 0 ? 0 : page - 1)).
size(itemsPerPage < 0 ? elasticsearchUtils.getIndexMaxResultWindow() : itemsPerPage).
sort(sortBuilders(kind, orderBy)).
diff --git a/ext/elasticsearch/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/dao/ElasticsearchAnySearchDAOTest.java b/ext/elasticsearch/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/dao/ElasticsearchAnySearchDAOTest.java
index 770cb766a1..e08aed8854 100644
--- a/ext/elasticsearch/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/dao/ElasticsearchAnySearchDAOTest.java
+++ b/ext/elasticsearch/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/dao/ElasticsearchAnySearchDAOTest.java
@@ -99,7 +99,7 @@ public class ElasticsearchAnySearchDAOTest {
// 2. test
Set<String> adminRealms = Set.of(SyncopeConstants.ROOT_REALM);
Triple<Optional<Query>, Set<String>, Set<String>> filter =
- searchDAO.getAdminRealmsFilter(AnyTypeKind.USER, adminRealms);
+ searchDAO.getAdminRealmsFilter(realmDAO.getRoot(), true, adminRealms, AnyTypeKind.USER);
assertThat(
new Query.Builder().disMax(QueryBuilders.disMax().queries(
@@ -122,7 +122,7 @@ public class ElasticsearchAnySearchDAOTest {
// 2. test
Set<String> adminRealms = Set.of("dyn");
Triple<Optional<Query>, Set<String>, Set<String>> filter =
- searchDAO.getAdminRealmsFilter(AnyTypeKind.USER, adminRealms);
+ searchDAO.getAdminRealmsFilter(realmDAO.getRoot(), true, adminRealms, AnyTypeKind.USER);
assertFalse(filter.getLeft().isPresent());
assertEquals(Set.of("dyn"), filter.getMiddle());
assertEquals(Set.of(), filter.getRight());
@@ -132,7 +132,7 @@ public class ElasticsearchAnySearchDAOTest {
public void getAdminRealmsFilter_groupOwner() {
Set<String> adminRealms = Set.of(RealmUtils.getGroupOwnerRealm("/any", "groupKey"));
Triple<Optional<Query>, Set<String>, Set<String>> filter =
- searchDAO.getAdminRealmsFilter(AnyTypeKind.USER, adminRealms);
+ searchDAO.getAdminRealmsFilter(realmDAO.getRoot(), true, adminRealms, AnyTypeKind.USER);
assertFalse(filter.getLeft().isPresent());
assertEquals(Set.of(), filter.getMiddle());
assertEquals(Set.of("groupKey"), filter.getRight());
@@ -164,7 +164,8 @@ public class ElasticsearchAnySearchDAOTest {
SearchRequest request = new SearchRequest.Builder().
index(ElasticsearchUtils.getContextDomainName(AuthContextUtils.getDomain(), AnyTypeKind.USER)).
searchType(SearchType.QueryThenFetch).
- query(searchDAO.getQuery(adminRealms, SearchCond.getLeaf(anyCond), AnyTypeKind.USER)).
+ query(searchDAO.getQuery(realmDAO.findByFullPath("/any"), true,
+ adminRealms, SearchCond.getLeaf(anyCond), AnyTypeKind.USER)).
from(1).
size(10).
build();
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 d755d046a9..65943b14c1 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
@@ -635,8 +635,7 @@ public class SCIMDataBinder {
if (output(attributes, excludedAttributes, "members")) {
int count = userLogic.search(searchCond,
- 1, 1, List.of(),
- SyncopeConstants.ROOT_REALM, false).getLeft();
+ 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(
@@ -645,6 +644,7 @@ public class SCIMDataBinder {
AnyDAO.DEFAULT_PAGE_SIZE,
List.of(),
SyncopeConstants.ROOT_REALM,
+ true,
false).
getRight();
users.forEach(userTO -> group.getMembers().add(new Member(
diff --git a/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/AbstractService.java b/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/AbstractService.java
index 708c08220f..51e30dfeea 100644
--- a/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/AbstractService.java
+++ b/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/AbstractService.java
@@ -181,6 +181,7 @@ abstract class AbstractService<R extends SCIMResource> {
itemsPerPage,
sort,
SyncopeConstants.ROOT_REALM,
+ true,
false);
if (result.getLeft() > confManager.get().getGeneralConf().getFilterMaxResults()) {
diff --git a/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/GroupServiceImpl.java b/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/GroupServiceImpl.java
index f75c3c0f93..37b038f004 100644
--- a/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/GroupServiceImpl.java
+++ b/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/GroupServiceImpl.java
@@ -127,8 +127,7 @@ public class GroupServiceImpl extends AbstractService<SCIMGroup> implements Grou
membCond.setGroup(id);
SearchCond searchCond = SearchCond.getLeaf(membCond);
int count = userLogic.search(searchCond,
- 1, 1, List.of(),
- SyncopeConstants.ROOT_REALM, false).getLeft();
+ 1, 1, List.of(), SyncopeConstants.ROOT_REALM, true, false).getLeft();
for (int page = 1; page <= (count / AnyDAO.DEFAULT_PAGE_SIZE) + 1; page++) {
beforeMembers.addAll(userLogic.search(
searchCond,
@@ -136,6 +135,7 @@ public class GroupServiceImpl extends AbstractService<SCIMGroup> implements Grou
AnyDAO.DEFAULT_PAGE_SIZE,
List.of(),
SyncopeConstants.ROOT_REALM,
+ true,
false).
getRight().stream().map(EntityTO::getKey).collect(Collectors.toSet()));
}
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SearchITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SearchITCase.java
index 6602e57523..6ccc7a7f68 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SearchITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SearchITCase.java
@@ -162,6 +162,13 @@ public class SearchITCase extends AbstractITCase {
assertTrue(matchingStar.getResult().stream().anyMatch(user -> "verdi".equals(user.getUsername())));
assertTrue(matchingStar.getResult().stream().anyMatch(user -> "rossini".equals(user.getUsername())));
assertEquals(union, matchingStar.getResult().stream().map(UserTO::getUsername).collect(Collectors.toSet()));
+
+ matchingStar = userService.search(
+ new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).recursive(false).
+ fiql(SyncopeClient.getUserSearchConditionBuilder().inGroups("*child").query()).
+ build());
+ assertTrue(matchingStar.getResult().stream().anyMatch(user -> "verdi".equals(user.getUsername())));
+ assertTrue(matchingStar.getResult().stream().noneMatch(user -> "rossini".equals(user.getUsername())));
}
@Test
diff --git a/pom.xml b/pom.xml
index 734724d67c..f7f8903c44 100644
--- a/pom.xml
+++ b/pom.xml
@@ -510,10 +510,10 @@ under the License.
<docker.mysql.version>8.0</docker.mysql.version>
<docker.mariadb.version>10</docker.mariadb.version>
- <jdbc.postgresql.version>42.3.4</jdbc.postgresql.version>
+ <jdbc.postgresql.version>42.3.5</jdbc.postgresql.version>
<jdbc.mysql.version>8.0.28</jdbc.mysql.version>
<jdbc.mariadb.version>2.7.5</jdbc.mariadb.version>
- <jdbc.mssql.version>10.2.0.jre</jdbc.mssql.version>
+ <jdbc.mssql.version>10.2.1.jre</jdbc.mssql.version>
<jdbc.oracle.version>21.5.0.0</jdbc.oracle.version>
<conf.directory>${project.build.directory}/test-classes</conf.directory>