From e04e9f0d44f6b149f40265cfc71c0e431634c06d Mon Sep 17 00:00:00 2001 From: marc Date: Thu, 12 Dec 2024 12:32:39 +0100 Subject: [PATCH] fix: Validate data sharing on program stage [DHIS2-17594][2.41] (#19425) * fix: Validate data sharing on program stage [DHIS2-17594][2.41] * fix: Validate data sharing on program stage [DHIS2-17594][2.41] --- .../DefaultTrackedEntityService.java | 5 +- .../TrackedEntityServiceTest.java | 60 ++++++++++++++++--- 2 files changed, 56 insertions(+), 9 deletions(-) diff --git a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/trackedentity/DefaultTrackedEntityService.java b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/trackedentity/DefaultTrackedEntityService.java index f54bef19b27b..ee7006010327 100644 --- a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/trackedentity/DefaultTrackedEntityService.java +++ b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/trackedentity/DefaultTrackedEntityService.java @@ -375,7 +375,10 @@ private Set getEnrollments( e -> { Set filteredEvents = e.getEvents().stream() - .filter(event -> includeDeleted || !event.isDeleted()) + .filter( + event -> + (includeDeleted || !event.isDeleted()) + && trackerAccessManager.canRead(user, event, false).isEmpty()) .collect(Collectors.toSet()); e.setEvents(filteredEvents); return e; diff --git a/dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/tracker/export/trackedentity/TrackedEntityServiceTest.java b/dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/tracker/export/trackedentity/TrackedEntityServiceTest.java index 58f5b0985f85..b6e88fb14672 100644 --- a/dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/tracker/export/trackedentity/TrackedEntityServiceTest.java +++ b/dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/tracker/export/trackedentity/TrackedEntityServiceTest.java @@ -103,6 +103,7 @@ import org.hisp.dhis.trackedentityattributevalue.TrackedEntityAttributeValue; import org.hisp.dhis.trackedentityattributevalue.TrackedEntityAttributeValueService; import org.hisp.dhis.user.User; +import org.hisp.dhis.user.UserDetails; import org.hisp.dhis.user.UserService; import org.hisp.dhis.user.sharing.Sharing; import org.junit.jupiter.api.Disabled; @@ -164,14 +165,12 @@ class TrackedEntityServiceTest extends IntegrationTestBase { private Enrollment enrollmentB; - private Enrollment enrollmentC; + private ProgramStage programStageA1; private Event eventA; private Event eventB; - private Event eventC; - private TrackedEntity trackedEntityA; private TrackedEntity trackedEntityB; @@ -180,8 +179,6 @@ class TrackedEntityServiceTest extends IntegrationTestBase { private TrackedEntity trackedEntityGrandchildA; - private Note note; - private CategoryOptionCombo defaultCategoryOptionCombo; private Relationship relationshipA; @@ -194,6 +191,8 @@ class TrackedEntityServiceTest extends IntegrationTestBase { private Relationship relationshipE; + private Note note; + private static List uids( Collection identifiableObjects) { return identifiableObjects.stream() @@ -282,7 +281,7 @@ protected void setUpTest() throws Exception { programA.setCategoryCombo(defaultCategoryCombo); programA.setMinAttributesRequiredToSearch(0); manager.save(programA, false); - ProgramStage programStageA1 = createProgramStage(programA); + programStageA1 = createProgramStage(programA); programStageA1.setPublicAccess(AccessStringHelper.FULL); manager.save(programStageA1, false); ProgramStage programStageA2 = createProgramStage(programA); @@ -399,10 +398,10 @@ protected void setUpTest() throws Exception { trackedEntityB.setTrackedEntityType(trackedEntityTypeA); manager.save(trackedEntityB, false); - enrollmentC = + Enrollment enrollmentC = enrollmentService.enrollTrackedEntity( trackedEntityB, programB, new Date(), new Date(), orgUnitB); - eventC = new Event(); + Event eventC = new Event(); eventC.setEnrollment(enrollmentC); eventC.setProgramStage(programStageB1); eventC.setOrganisationUnit(orgUnitB); @@ -2071,6 +2070,51 @@ void shouldReturnTrackedEntityTypeAttributesWhenSingleTERequestedAndNoProgramSpe trackedEntity.getTrackedEntityAttributeValues()); } + @Test + void shouldFindTrackedEntityWithEventsWhenEventRequestedAndAccessible() + throws ForbiddenException, NotFoundException, BadRequestException { + injectSecurityContextUser(getAdminUser()); + User testUser = createAndAddUser(false, "testUser", emptySet(), emptySet(), "F_EXPORT_DATA"); + testUser.setOrganisationUnits(Set.of(orgUnitA)); + manager.update(testUser); + injectSecurityContext(UserDetails.fromUser(testUser)); + + TrackedEntity trackedEntity = + trackedEntityService.getTrackedEntity( + trackedEntityA.getUid(), programA.getUid(), TrackedEntityParams.TRUE, false); + + assertEquals(trackedEntityA.getUid(), trackedEntity.getUid()); + assertContainsOnly(Set.of(enrollmentA.getUid()), uids(trackedEntity.getEnrollments())); + List enrollments = new ArrayList<>(trackedEntity.getEnrollments()); + Optional enrollment = + enrollments.stream().filter(e -> e.getUid().equals(this.enrollmentA.getUid())).findFirst(); + Set events = enrollment.get().getEvents(); + assertContainsOnly(Set.of(eventA.getUid()), uids(events)); + } + + @Test + void shouldFindTrackedEntityWithoutEventsWhenEventRequestedButNotAccessible() + throws ForbiddenException, NotFoundException, BadRequestException { + injectSecurityContextUser(getAdminUser()); + programStageA1.setSharing(Sharing.builder().publicAccess("--------").build()); + manager.update(programStageA1); + User testUser = createAndAddUser(false, "testUser", emptySet(), emptySet(), "F_EXPORT_DATA"); + testUser.setOrganisationUnits(Set.of(orgUnitA)); + manager.update(testUser); + injectSecurityContext(UserDetails.fromUser(testUser)); + + TrackedEntity trackedEntity = + trackedEntityService.getTrackedEntity( + trackedEntityA.getUid(), programA.getUid(), TrackedEntityParams.TRUE, false); + + assertEquals(trackedEntityA.getUid(), trackedEntity.getUid()); + assertContainsOnly(Set.of(enrollmentA.getUid()), uids(trackedEntity.getEnrollments())); + List enrollments = new ArrayList<>(trackedEntity.getEnrollments()); + Optional enrollment = + enrollments.stream().filter(e -> e.getUid().equals(this.enrollmentA.getUid())).findFirst(); + assertIsEmpty(enrollment.get().getEvents()); + } + private Set attributeNames(final Collection attributes) { // depends on createTrackedEntityAttribute() prefixing with "Attribute" return attributes.stream()