From 0b752beeefa9624ba2befa3e9fe4c942bfb2b834 Mon Sep 17 00:00:00 2001 From: muilpp Date: Thu, 2 Nov 2023 15:57:15 +0100 Subject: [PATCH] fix: Return search scope and capture scope for events [TECH-1663][2.38] --- .../dxf2/events/event/EventQueryParams.java | 2 - .../dxf2/events/event/JdbcEventStore.java | 109 ++++++++++-------- .../RegistrationMultiEventsServiceTest.java | 3 +- .../hisp/dhis/tracker/EventExporterTest.java | 6 +- 4 files changed, 69 insertions(+), 51 deletions(-) diff --git a/dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/EventQueryParams.java b/dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/EventQueryParams.java index 7ddb1997e549..1156f942a9b4 100644 --- a/dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/EventQueryParams.java +++ b/dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/EventQueryParams.java @@ -110,8 +110,6 @@ public class EventQueryParams { private Boolean followUp; - // TODO Default set to DESCENDANTS to replicate master, but this will need to be fixed in - // https://dhis2.atlassian.net/browse/TECH-1588 private OrganisationUnitSelectionMode orgUnitSelectionMode = OrganisationUnitSelectionMode.ACCESSIBLE; diff --git a/dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/JdbcEventStore.java b/dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/JdbcEventStore.java index 38e4fa9b6d82..6bda6eec573e 100644 --- a/dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/JdbcEventStore.java +++ b/dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/JdbcEventStore.java @@ -187,6 +187,13 @@ public class JdbcEventStore implements EventStore { private static final String DOT_NAME = ".name)"; + private static final String USER_SCOPE_ORG_UNIT_PATH_LIKE_MATCH_QUERY = + " ou.path like CONCAT(orgunit.path, '%') "; + + private static String getCustomOrgUnitPathLikeMatchQuery(String orgUnitPath) { + return " ou.path like CONCAT('" + orgUnitPath + "', '%' ) "; + } + private static final Map QUERY_PARAM_COL_MAP = ImmutableMap.builder() .put(EVENT_ID, "psi_uid") @@ -322,10 +329,6 @@ public class JdbcEventStore implements EventStore { + " where uid = ?;"; } - private static final String COLUMN_USER_UID = "u_uid"; - - private static final String COLUMN_ORG_UNIT_PATH = "ou_path"; - private static final String PERCENTAGE_SIGN = ", '%' "; // ------------------------------------------------------------------------- @@ -1310,75 +1313,91 @@ private String createAccessibleSql(User user, EventQueryParams params) { return createCaptureSql(user); } - return " EXISTS(SELECT ss.organisationunitid " - + " FROM userteisearchorgunits ss " - + " JOIN organisationunit orgunit ON orgunit.organisationunitid = ss.organisationunitid " - + " JOIN userinfo u ON u.userinfoid = ss.userinfoid " - + " WHERE u.uid = '" - + user.getUid() - + "'" - + " AND ou.path like CONCAT(orgunit.path, '%')) "; + return getSearchAndCaptureScopeOrgUnitPathMatchQuery( + USER_SCOPE_ORG_UNIT_PATH_LIKE_MATCH_QUERY, user.getUid()); } private String createDescendantsSql(User user, EventQueryParams params) { if (isProgramRestricted(params.getProgram())) { return createCaptureScopeQuery( - user, - " AND ou.path like CONCAT('" - + params.getOrgUnit().getPath() - + "'" - + PERCENTAGE_SIGN - + ")"); + user, " AND " + getCustomOrgUnitPathLikeMatchQuery(params.getOrgUnit().getPath())); } - return " ou.path like CONCAT('" + params.getOrgUnit().getPath() + "'" + PERCENTAGE_SIGN + ") "; + return getSearchAndCaptureScopeOrgUnitPathMatchQuery( + getCustomOrgUnitPathLikeMatchQuery(params.getOrgUnit().getPath()), user.getUid()); } private String createChildrenSql(User user, EventQueryParams params) { + String customChildrenQuery = + " AND (ou.hierarchylevel = " + + params.getOrgUnit().getHierarchyLevel() + + " OR ou.hierarchylevel = " + + (params.getOrgUnit().getHierarchyLevel() + 1) + + " ) "; + if (isProgramRestricted(params.getProgram())) { - String childrenSqlClause = - " AND ou.path like CONCAT('" - + params.getOrgUnit().getPath() - + "'" - + PERCENTAGE_SIGN - + ") " - + " AND (ou.hierarchylevel = " - + params.getOrgUnit().getHierarchyLevel() - + " OR ou.hierarchylevel = " - + (params.getOrgUnit().getHierarchyLevel() + 1) - + " )"; - - return createCaptureScopeQuery(user, childrenSqlClause); - } - - return " ou.path like CONCAT('" - + params.getOrgUnit().getPath() - + "'" - + PERCENTAGE_SIGN - + ") " - + " AND (ou.hierarchylevel = " - + params.getOrgUnit().getHierarchyLevel() - + " OR ou.hierarchylevel = " - + (params.getOrgUnit().getHierarchyLevel() + 1) - + " ) "; + return createCaptureScopeQuery( + user, + " AND " + + getCustomOrgUnitPathLikeMatchQuery(params.getOrgUnit().getPath()) + + customChildrenQuery); + } + + return getSearchAndCaptureScopeOrgUnitPathMatchQuery( + getCustomOrgUnitPathLikeMatchQuery(params.getOrgUnit().getPath()) + customChildrenQuery, + user.getUid()); } private String createSelectedSql(User user, EventQueryParams params) { + String orgUnitPathEqualsMatchQuery = + " ou.path = '" + + params.getOrgUnit().getPath() + + "' " + + " AND " + + USER_SCOPE_ORG_UNIT_PATH_LIKE_MATCH_QUERY; + if (isProgramRestricted(params.getProgram())) { String customSelectedClause = " AND ou.path = '" + params.getOrgUnit().getPath() + "' "; return createCaptureScopeQuery(user, customSelectedClause); } - return " ou.path = '" + params.getOrgUnit().getPath() + "' "; + return getSearchAndCaptureScopeOrgUnitPathMatchQuery( + orgUnitPathEqualsMatchQuery, user.getUid()); } private boolean isProgramRestricted(Program program) { return program != null && (program.isProtected() || program.isClosed()); } + private static String getSearchAndCaptureScopeOrgUnitPathMatchQuery( + String orgUnitMatcher, String userId) { + return " (EXISTS(SELECT ss.organisationunitid " + + " FROM userteisearchorgunits ss " + + " JOIN userinfo u ON u.userinfoid = ss.userinfoid " + + " JOIN organisationunit orgunit ON orgunit.organisationunitid = ss.organisationunitid " + + " WHERE u.uid = " + + "'" + + userId + + "'" + + " AND " + + orgUnitMatcher + + " AND p.accesslevel in ('OPEN', 'AUDITED')) " + + " OR EXISTS(SELECT cs.organisationunitid " + + " FROM usermembership cs " + + " JOIN userinfo u ON u.userinfoid = cs.userinfoid " + + " JOIN organisationunit orgunit ON orgunit.organisationunitid = cs.organisationunitid " + + " WHERE u.uid = " + + "'" + + userId + + "'" + + " AND " + + orgUnitMatcher + + " )) "; + } + private boolean isUserSearchScopeNotSet(User user) { return user.getTeiSearchOrganisationUnits().isEmpty(); } diff --git a/dhis-2/dhis-services/dhis-service-dxf2/src/test/java/org/hisp/dhis/dxf2/events/RegistrationMultiEventsServiceTest.java b/dhis-2/dhis-services/dhis-service-dxf2/src/test/java/org/hisp/dhis/dxf2/events/RegistrationMultiEventsServiceTest.java index 2f295c7199ca..5ce1ec3bd404 100644 --- a/dhis-2/dhis-services/dhis-service-dxf2/src/test/java/org/hisp/dhis/dxf2/events/RegistrationMultiEventsServiceTest.java +++ b/dhis-2/dhis-services/dhis-service-dxf2/src/test/java/org/hisp/dhis/dxf2/events/RegistrationMultiEventsServiceTest.java @@ -35,6 +35,7 @@ import com.google.common.collect.Lists; import java.util.Date; import java.util.HashSet; +import java.util.Set; import org.hamcrest.CoreMatchers; import org.hisp.dhis.TransactionalIntegrationTest; import org.hisp.dhis.common.CodeGenerator; @@ -165,7 +166,7 @@ protected void setUpTest() throws Exception { manager.update(programStageA); manager.update(programStageB); manager.update(programA); - createUserAndInjectSecurityContext(true); + createUserAndInjectSecurityContext(Set.of(organisationUnitA, organisationUnitB), true); } @Test diff --git a/dhis-2/dhis-services/dhis-service-tracker/src/test/java/org/hisp/dhis/tracker/EventExporterTest.java b/dhis-2/dhis-services/dhis-service-tracker/src/test/java/org/hisp/dhis/tracker/EventExporterTest.java index 5d1ca73d7502..2fb4053b86a3 100644 --- a/dhis-2/dhis-services/dhis-service-tracker/src/test/java/org/hisp/dhis/tracker/EventExporterTest.java +++ b/dhis-2/dhis-services/dhis-service-tracker/src/test/java/org/hisp/dhis/tracker/EventExporterTest.java @@ -27,6 +27,7 @@ */ package org.hisp.dhis.tracker; +import static org.hisp.dhis.common.OrganisationUnitSelectionMode.SELECTED; import static org.hisp.dhis.util.DateUtils.parseDate; import static org.hisp.dhis.utils.Assertions.assertContains; import static org.hisp.dhis.utils.Assertions.assertContainsOnly; @@ -50,7 +51,6 @@ import org.hisp.dhis.common.IdSchemes; import org.hisp.dhis.common.IdentifiableObject; import org.hisp.dhis.common.IdentifiableObjectManager; -import org.hisp.dhis.common.OrganisationUnitSelectionMode; import org.hisp.dhis.common.Pager; import org.hisp.dhis.common.SlimPager; import org.hisp.dhis.dxf2.events.event.Event; @@ -183,7 +183,7 @@ void shouldReturnPaginatedEventsWithNotesGivenNonDefaultPageSize() { @Test void testExportEvents() { EventQueryParams params = new EventQueryParams(); - params.setOrgUnitSelectionMode(OrganisationUnitSelectionMode.SELECTED); + params.setOrgUnitSelectionMode(SELECTED); params.setOrgUnit(orgUnit); List events = eventsFunction.apply(params); @@ -195,7 +195,7 @@ void testExportEvents() { @Test void testExportEventsWhenFilteringByEnrollment() { EventQueryParams params = new EventQueryParams(); - params.setOrgUnitSelectionMode(OrganisationUnitSelectionMode.SELECTED); + params.setOrgUnitSelectionMode(SELECTED); params.setOrgUnit(orgUnit); params.setProgramInstances(Set.of("nxP7UnKhomJ"));