Skip to content

Commit

Permalink
fix: Skip validations if user is superuser [TECH-1589][2.38] (#15651)
Browse files Browse the repository at this point in the history
  • Loading branch information
muilpp authored Nov 11, 2023
1 parent 9a6894c commit 636ce03
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,12 @@
*/
package org.hisp.dhis.trackedentity;

import static org.hisp.dhis.common.AccessLevel.CLOSED;
import static org.hisp.dhis.common.OrganisationUnitSelectionMode.ALL;
import static org.hisp.dhis.trackedentity.TrackedEntityInstanceQueryParams.OrderColumn.ENROLLED_AT;
import static org.hisp.dhis.utils.Assertions.assertContains;
import static org.hisp.dhis.utils.Assertions.assertIsEmpty;
import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
Expand All @@ -43,6 +47,7 @@
import java.util.stream.Collectors;
import org.hisp.dhis.IntegrationTestBase;
import org.hisp.dhis.common.Grid;
import org.hisp.dhis.common.IllegalQueryException;
import org.hisp.dhis.common.QueryFilter;
import org.hisp.dhis.common.QueryItem;
import org.hisp.dhis.common.QueryOperator;
Expand All @@ -57,6 +62,7 @@
import org.hisp.dhis.program.ProgramStageInstance;
import org.hisp.dhis.program.ProgramStageInstanceService;
import org.hisp.dhis.program.ProgramStageService;
import org.hisp.dhis.program.ProgramType;
import org.hisp.dhis.security.acl.AccessStringHelper;
import org.hisp.dhis.trackedentityattributevalue.TrackedEntityAttributeValue;
import org.hisp.dhis.trackedentityattributevalue.TrackedEntityAttributeValueService;
Expand Down Expand Up @@ -124,6 +130,10 @@ class TrackedEntityInstanceServiceTest extends IntegrationTestBase {

private static final String ATTRIBUTE_VALUE = "Value";

private User userWithSearchInAllAuthority;

private Program disabledAccessProgram;

@Override
public boolean emptyDatabaseAfterTest() {
return true;
Expand Down Expand Up @@ -173,7 +183,18 @@ public void setUpTest() {
attributeService.addTrackedEntityAttribute(attrE);
attributeService.addTrackedEntityAttribute(filtF);
attributeService.addTrackedEntityAttribute(filtG);

disabledAccessProgram = createProgram('C', new HashSet<>(), null);
disabledAccessProgram.setProgramType(ProgramType.WITH_REGISTRATION);
disabledAccessProgram.setAccessLevel(CLOSED);
disabledAccessProgram.getSharing().setPublicAccess(AccessStringHelper.disableDataSharing(null));
programService.addProgram(disabledAccessProgram);

super.userService = this.userService;

userWithSearchInAllAuthority =
createUser("userSearchInAll", "F_TRACKED_ENTITY_INSTANCE_SEARCH_IN_ALL_ORGUNITS");

User user = createUser("testUser");
user.setTeiSearchOrganisationUnits(Sets.newHashSet(organisationUnit));
CurrentUserService currentUserService = new MockCurrentUserService(user);
Expand Down Expand Up @@ -917,6 +938,47 @@ void shouldReturnEmptyIfTEWasUpdatedBeforePassedDateAndTime() {
assertIsEmpty(trackedEntities);
}

@Test
void shouldFailWhenModeAllUserCanSearchEverywhereButNotSuperuserAndNoAccessToProgram() {
injectSecurityContext(userWithSearchInAllAuthority);

TrackedEntityInstanceQueryParams params = new TrackedEntityInstanceQueryParams();
params.setOrganisationUnitMode(ALL);
params.setProgram(disabledAccessProgram);
params.setUser(userWithSearchInAllAuthority);

IllegalQueryException ex =
assertThrows(
IllegalQueryException.class,
() -> entityInstanceService.getTrackedEntityInstanceIds(params, false, false));

assertContains(
String.format(
"Current user is not authorized to read data from selected program: %s",
disabledAccessProgram.getUid()),
ex.getMessage());
}

@Test
void shouldReturnAllEntitiesWhenSuperuserAndModeAll() {
injectSecurityContext(createAndInjectAdminUser(ALL.name()));
addEntityInstances();

TrackedEntityInstanceQueryParams params = new TrackedEntityInstanceQueryParams();
params.setOrganisationUnitMode(ALL);
params.setOrganisationUnits(Set.of(organisationUnit));

List<Long> trackedEntities =
entityInstanceService.getTrackedEntityInstanceIds(params, true, true);

assertEquals(4, trackedEntities.size());
assertAll(
() -> trackedEntities.contains(entityInstanceA1.getId()),
() -> trackedEntities.contains(entityInstanceB1.getId()),
() -> trackedEntities.contains(entityInstanceC1.getId()),
() -> trackedEntities.contains(entityInstanceD1.getId()));
}

private void initializeEntityInstance(TrackedEntityInstance entityInstance) {
entityInstance.setTrackedEntityType(trackedEntityType);
entityInstanceService.addTrackedEntityInstance(entityInstance);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
*/
package org.hisp.dhis.dxf2.events.security;

import static org.hisp.dhis.common.OrganisationUnitSelectionMode.ALL;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
Expand Down Expand Up @@ -103,6 +104,8 @@ class EnrollmentSecurityTest extends TransactionalIntegrationTest {

private ProgramStage programStageB;

private User admin;

@Override
public boolean emptyDatabaseAfterTest() {
return true;
Expand All @@ -111,7 +114,7 @@ public boolean emptyDatabaseAfterTest() {
@Override
protected void setUpTest() {
userService = _userService;
User admin = createAndInjectAdminUser();
admin = createAndInjectAdminUser();
organisationUnitA = createOrganisationUnit('A');
organisationUnitB = createOrganisationUnit('B');
manager.save(organisationUnitA);
Expand Down Expand Up @@ -435,6 +438,23 @@ void testAddEnrollmentWithOrgUnitIdSchemeToOrgUnitWithoutProgramAccess() {
assertEquals(ImportStatus.SUCCESS, importSummary.getStatus());
}

@Test
void shouldReturnAllEnrollmentsWhenOrgUnitModeAllAndUserAuthorized() {
ImportSummary importSummary =
enrollmentService.addEnrollment(
createEnrollment(programA.getUid(), maleA.getUid()),
ImportOptions.getDefaultImportOptions());
assertEquals(ImportStatus.SUCCESS, importSummary.getStatus());

injectSecurityContext(admin);
ProgramInstanceQueryParams params = new ProgramInstanceQueryParams();
params.setOrganisationUnitMode(ALL);
params.setUser(admin);

Enrollments enrollments = enrollmentService.getEnrollments(params);
assertNotNull(enrollments);
}

private Enrollment createEnrollment(String program, String person) {
Enrollment enrollment = new Enrollment();
enrollment.setEnrollment(CodeGenerator.generateUid());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
package org.hisp.dhis.webapi.controller.event.mapper;

import static org.apache.commons.lang3.BooleanUtils.toBooleanDefaultIfNull;
import static org.hisp.dhis.common.OrganisationUnitSelectionMode.ALL;
import static org.hisp.dhis.webapi.controller.event.mapper.OrderParamsHelper.toOrderParams;

import java.util.Date;
Expand All @@ -45,6 +46,7 @@
import org.hisp.dhis.program.ProgramInstanceQueryParams;
import org.hisp.dhis.program.ProgramService;
import org.hisp.dhis.program.ProgramStatus;
import org.hisp.dhis.security.Authorities;
import org.hisp.dhis.trackedentity.TrackedEntityInstance;
import org.hisp.dhis.trackedentity.TrackedEntityInstanceService;
import org.hisp.dhis.trackedentity.TrackedEntityType;
Expand Down Expand Up @@ -144,6 +146,13 @@ public ProgramInstanceQueryParams getFromUrl(
throw new IllegalQueryException("Program does not exist: " + program);
}

if (params.isOrganisationUnitMode(ALL)
&& !currentUserService.currentUserIsAuthorized(
Authorities.F_TRACKED_ENTITY_INSTANCE_SEARCH_IN_ALL_ORGUNITS.name())) {
throw new IllegalQueryException(
"Current user is not authorized to query across all organisation units");
}

TrackedEntityType te =
trackedEntityType != null
? trackedEntityTypeService.getTrackedEntityType(trackedEntityType)
Expand Down

0 comments on commit 636ce03

Please sign in to comment.