Skip to content

Commit

Permalink
fix: Return search scope and capture scope for events [TECH-1663][2.3…
Browse files Browse the repository at this point in the history
…8] (#15578)
  • Loading branch information
muilpp authored Nov 3, 2023
1 parent f416b41 commit 7b48ce6
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 51 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<String, String> QUERY_PARAM_COL_MAP =
ImmutableMap.<String, String>builder()
.put(EVENT_ID, "psi_uid")
Expand Down Expand Up @@ -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 = ", '%' ";

// -------------------------------------------------------------------------
Expand Down Expand Up @@ -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();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -183,7 +183,7 @@ void shouldReturnPaginatedEventsWithNotesGivenNonDefaultPageSize() {
@Test
void testExportEvents() {
EventQueryParams params = new EventQueryParams();
params.setOrgUnitSelectionMode(OrganisationUnitSelectionMode.SELECTED);
params.setOrgUnitSelectionMode(SELECTED);
params.setOrgUnit(orgUnit);

List<String> events = eventsFunction.apply(params);
Expand All @@ -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"));

Expand Down

0 comments on commit 7b48ce6

Please sign in to comment.