Skip to content

Commit

Permalink
fix: Validate data sharing on program stage [DHIS2-17594] (#19423)
Browse files Browse the repository at this point in the history
* fix: Validate data sharing on program stage [DHIS2-17594]

* fix: Validate data sharing on program stage [DHIS2-17594]
  • Loading branch information
muilpp authored Dec 10, 2024
1 parent 99c00a5 commit 1d49336
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,10 @@ private Set<Enrollment> getEnrollments(
e -> {
Set<Event> 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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,8 @@ class TrackedEntityServiceTest extends PostgresIntegrationTestBase {

private Enrollment enrollmentB;

private ProgramStage programStageA1;

private Event eventA;

private Event eventB;
Expand All @@ -173,8 +175,6 @@ class TrackedEntityServiceTest extends PostgresIntegrationTestBase {

private TrackedEntity trackedEntityGrandchildA;

private Note note;

private CategoryOptionCombo defaultCategoryOptionCombo;

private Relationship relationshipA;
Expand Down Expand Up @@ -270,7 +270,7 @@ void setUp() {
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);
Expand Down Expand Up @@ -360,7 +360,7 @@ void setUp() {
eventA.setCompletedDate(parseDate("2021-02-27T11:05:00.000"));
eventA.setCompletedBy("herb");
eventA.setAssignedUser(user);
note = new Note("note1", "ant");
Note note = new Note("note1", "ant");
note.setUid(generateUid());
note.setCreated(new Date());
note.setLastUpdated(new Date());
Expand Down Expand Up @@ -1342,6 +1342,37 @@ void shouldReturnTrackedEntityWithoutEventsGivenTheyShouldNotBeIncluded()
assertIsEmpty(enrollmentA.get().getEvents());
}

@Test
void shouldReturnTrackedEntityWithoutEventWhenProgramStageNotAccessible()
throws ForbiddenException, BadRequestException, NotFoundException {
injectAdminIntoSecurityContext();
programStageA1.setSharing(Sharing.builder().publicAccess("--------").build());
manager.update(programStageA1);
injectSecurityContextUser(user);
TrackedEntityParams params = new TrackedEntityParams(false, TRUE, true, false);
TrackedEntityOperationParams operationParams =
TrackedEntityOperationParams.builder()
.organisationUnits(orgUnitA)
.orgUnitMode(SELECTED)
.trackedEntityType(trackedEntityTypeA)
.trackedEntities(trackedEntityA)
.trackedEntityParams(params)
.build();

List<TrackedEntity> trackedEntities = trackedEntityService.getTrackedEntities(operationParams);

assertContainsOnly(List.of(trackedEntityA), trackedEntities);
assertContainsOnly(
Set.of(enrollmentA.getUid(), enrollmentB.getUid()),
uids(trackedEntities.get(0).getEnrollments()));
List<Enrollment> enrollments = new ArrayList<>(trackedEntities.get(0).getEnrollments());
Optional<Enrollment> enrollmentA =
enrollments.stream()
.filter(enrollment -> enrollment.getUid().equals(this.enrollmentA.getUid()))
.findFirst();
assertIsEmpty(enrollmentA.get().getEvents());
}

@Test
void shouldReturnTrackedEntityMappedCorrectly()
throws ForbiddenException, NotFoundException, BadRequestException {
Expand Down Expand Up @@ -2023,6 +2054,55 @@ void shouldReturnTrackedEntityTypeAttributesWhenSingleTERequestedAndNoProgramSpe
UID.of(trackedEntityA), UID.of(programA), TrackedEntityParams.TRUE));
}

@Test
void shouldFindTrackedEntityWithEventsWhenEventRequestedAndAccessible()
throws ForbiddenException, NotFoundException, BadRequestException {
injectAdminIntoSecurityContext();
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(
UID.of(trackedEntityA), UID.of(programA), TrackedEntityParams.TRUE);

assertEquals(trackedEntityA.getUid(), trackedEntity.getUid());
assertContainsOnly(Set.of(enrollmentA.getUid()), uids(trackedEntity.getEnrollments()));
List<Enrollment> enrollments = new ArrayList<>(trackedEntity.getEnrollments());
Optional<Enrollment> enrollmentA =
enrollments.stream()
.filter(enrollment -> enrollment.getUid().equals(this.enrollmentA.getUid()))
.findFirst();
Set<Event> events = enrollmentA.get().getEvents();
assertContainsOnly(Set.of(eventA.getUid()), uids(events));
}

@Test
void shouldFindTrackedEntityWithoutEventsWhenEventRequestedButNotAccessible()
throws ForbiddenException, NotFoundException, BadRequestException {
injectAdminIntoSecurityContext();
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(
UID.of(trackedEntityA), UID.of(programA), TrackedEntityParams.TRUE);

assertEquals(trackedEntityA.getUid(), trackedEntity.getUid());
assertContainsOnly(Set.of(enrollmentA.getUid()), uids(trackedEntity.getEnrollments()));
List<Enrollment> enrollments = new ArrayList<>(trackedEntity.getEnrollments());
Optional<Enrollment> enrollmentA =
enrollments.stream()
.filter(enrollment -> enrollment.getUid().equals(this.enrollmentA.getUid()))
.findFirst();
assertIsEmpty(enrollmentA.get().getEvents());
}

private Set<String> attributeNames(final Collection<TrackedEntityAttributeValue> attributes) {
// depends on createTrackedEntityAttribute() prefixing with "Attribute"
return attributes.stream()
Expand Down

0 comments on commit 1d49336

Please sign in to comment.