From 2b838ae384f75401480b8378e3eaa3a61f8d1437 Mon Sep 17 00:00:00 2001 From: Enrico Date: Fri, 31 Jan 2025 15:00:56 +0100 Subject: [PATCH 1/2] chore: Remove entities service dependency from relationship service [DHIS2-18883] --- .../HibernateRelationshipStore.java | 45 + .../RelationshipOperationParamsMapper.java | 63 +- .../relationship/RelationshipStore.java | 8 + ...RelationshipOperationParamsMapperTest.java | 38 +- .../controller/tracker/JsonAssertions.java | 9 +- .../RelationshipsExportControllerTest.java | 1538 +++++++---------- .../tracker/event_and_enrollment.json | 2 +- 7 files changed, 787 insertions(+), 916 deletions(-) diff --git a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/relationship/HibernateRelationshipStore.java b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/relationship/HibernateRelationshipStore.java index 90c1715f9e8c..269189807bfb 100644 --- a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/relationship/HibernateRelationshipStore.java +++ b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/relationship/HibernateRelationshipStore.java @@ -38,6 +38,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Optional; import java.util.Set; import java.util.function.Function; import java.util.function.LongSupplier; @@ -47,6 +48,7 @@ import org.hisp.dhis.common.IdentifiableObject; import org.hisp.dhis.common.SoftDeletableObject; import org.hisp.dhis.common.SortDirection; +import org.hisp.dhis.common.UID; import org.hisp.dhis.common.hibernate.SoftDeleteHibernateObjectStore; import org.hisp.dhis.program.Enrollment; import org.hisp.dhis.program.Event; @@ -88,6 +90,49 @@ public HibernateRelationshipStore( super(entityManager, jdbcTemplate, publisher, Relationship.class, aclService, true); } + @Override + public Optional findTrackedEntity(UID trackedEntity) { + @Language("hql") + String hql = + """ + from TrackedEntity te + where te.uid = :trackedEntity + """; + List trackedEntities = + getQuery(hql, TrackedEntity.class) + .setParameter(TRACKED_ENTITY, trackedEntity.getValue()) + .getResultList(); + return trackedEntities.stream().findFirst(); + } + + @Override + public Optional findEnrollment(UID enrollment) { + @Language("hql") + String hql = + """ + from Enrollment e + where e.uid = :enrollment + """; + List enrollments = + getQuery(hql, Enrollment.class) + .setParameter(ENROLLMENT, enrollment.getValue()) + .getResultList(); + return enrollments.stream().findFirst(); + } + + @Override + public Optional findEvent(UID event) { + @Language("hql") + String hql = + """ + from Event e + where e.uid = :event + """; + List events = + getQuery(hql, Event.class).setParameter(EVENT, event.getValue()).getResultList(); + return events.stream().findFirst(); + } + @Override public List getByTrackedEntity( TrackedEntity trackedEntity, RelationshipQueryParams queryParams) { diff --git a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/relationship/RelationshipOperationParamsMapper.java b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/relationship/RelationshipOperationParamsMapper.java index 6b558714052b..6a7e9ae9fe07 100644 --- a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/relationship/RelationshipOperationParamsMapper.java +++ b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/relationship/RelationshipOperationParamsMapper.java @@ -30,12 +30,14 @@ import javax.annotation.Nonnull; import lombok.RequiredArgsConstructor; import org.hisp.dhis.common.IdentifiableObject; -import org.hisp.dhis.feedback.BadRequestException; +import org.hisp.dhis.common.UID; import org.hisp.dhis.feedback.ForbiddenException; import org.hisp.dhis.feedback.NotFoundException; -import org.hisp.dhis.tracker.export.enrollment.EnrollmentService; -import org.hisp.dhis.tracker.export.event.EventService; -import org.hisp.dhis.tracker.export.trackedentity.TrackedEntityService; +import org.hisp.dhis.program.Enrollment; +import org.hisp.dhis.program.Event; +import org.hisp.dhis.trackedentity.TrackedEntity; +import org.hisp.dhis.tracker.acl.TrackerAccessManager; +import org.hisp.dhis.user.CurrentUserUtil; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; @@ -47,19 +49,18 @@ @RequiredArgsConstructor class RelationshipOperationParamsMapper { - private final TrackedEntityService trackedEntityService; - private final EnrollmentService enrollmentService; - private final EventService eventService; + private final RelationshipStore relationshipStore; + private final TrackerAccessManager trackerAccessManager; @Transactional(readOnly = true) public RelationshipQueryParams map(@Nonnull RelationshipOperationParams params) - throws NotFoundException, ForbiddenException, BadRequestException { + throws NotFoundException, ForbiddenException { IdentifiableObject entity = switch (params.getType()) { - case TRACKED_ENTITY -> trackedEntityService.getTrackedEntity(params.getIdentifier()); - case ENROLLMENT -> enrollmentService.getEnrollment(params.getIdentifier()); - case EVENT -> eventService.getEvent(params.getIdentifier()); + case TRACKED_ENTITY -> getTrackedEntity(params.getIdentifier()); + case ENROLLMENT -> getEnrollment(params.getIdentifier()); + case EVENT -> getEvent(params.getIdentifier()); case RELATIONSHIP -> throw new IllegalArgumentException("Unsupported type"); }; @@ -69,4 +70,44 @@ public RelationshipQueryParams map(@Nonnull RelationshipOperationParams params) .includeDeleted(params.isIncludeDeleted()) .build(); } + + private TrackedEntity getTrackedEntity(UID trackedEntityUid) + throws NotFoundException, ForbiddenException { + TrackedEntity trackedEntity = + relationshipStore + .findTrackedEntity(trackedEntityUid) + .orElseThrow(() -> new NotFoundException(TrackedEntity.class, trackedEntityUid)); + if (!trackerAccessManager + .canRead(CurrentUserUtil.getCurrentUserDetails(), trackedEntity) + .isEmpty()) { + throw new ForbiddenException(TrackedEntity.class, trackedEntityUid); + } + return trackedEntity; + } + + private Enrollment getEnrollment(UID enrollmentUid) throws NotFoundException, ForbiddenException { + Enrollment enrollment = + relationshipStore + .findEnrollment(enrollmentUid) + .orElseThrow(() -> new NotFoundException(Enrollment.class, enrollmentUid)); + if (!trackerAccessManager + .canRead(CurrentUserUtil.getCurrentUserDetails(), enrollment, false) + .isEmpty()) { + throw new ForbiddenException(Enrollment.class, enrollmentUid); + } + return enrollment; + } + + private Event getEvent(UID eventUid) throws NotFoundException, ForbiddenException { + Event event = + relationshipStore + .findEvent(eventUid) + .orElseThrow(() -> new NotFoundException(Event.class, eventUid)); + if (!trackerAccessManager + .canRead(CurrentUserUtil.getCurrentUserDetails(), event, false) + .isEmpty()) { + throw new ForbiddenException(Event.class, eventUid); + } + return event; + } } diff --git a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/relationship/RelationshipStore.java b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/relationship/RelationshipStore.java index 0bc854263f50..aad60640c66b 100644 --- a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/relationship/RelationshipStore.java +++ b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/relationship/RelationshipStore.java @@ -28,8 +28,10 @@ package org.hisp.dhis.tracker.export.relationship; import java.util.List; +import java.util.Optional; import java.util.Set; import org.hisp.dhis.common.IdentifiableObjectStore; +import org.hisp.dhis.common.UID; import org.hisp.dhis.program.Enrollment; import org.hisp.dhis.program.Event; import org.hisp.dhis.relationship.Relationship; @@ -40,6 +42,12 @@ public interface RelationshipStore extends IdentifiableObjectStore { String ID = RelationshipStore.class.getName(); + Optional findTrackedEntity(UID trackedEntity); + + Optional findEnrollment(UID enrollment); + + Optional findEvent(UID event); + List getByTrackedEntity( TrackedEntity trackedEntity, RelationshipQueryParams queryParams); diff --git a/dhis-2/dhis-services/dhis-service-tracker/src/test/java/org/hisp/dhis/tracker/export/relationship/RelationshipOperationParamsMapperTest.java b/dhis-2/dhis-services/dhis-service-tracker/src/test/java/org/hisp/dhis/tracker/export/relationship/RelationshipOperationParamsMapperTest.java index f747fcb23ea2..2341d54c16bd 100644 --- a/dhis-2/dhis-services/dhis-service-tracker/src/test/java/org/hisp/dhis/tracker/export/relationship/RelationshipOperationParamsMapperTest.java +++ b/dhis-2/dhis-services/dhis-service-tracker/src/test/java/org/hisp/dhis/tracker/export/relationship/RelationshipOperationParamsMapperTest.java @@ -36,9 +36,9 @@ import static org.mockito.Mockito.when; import java.util.List; +import java.util.Optional; import org.hisp.dhis.common.SortDirection; import org.hisp.dhis.common.UID; -import org.hisp.dhis.feedback.BadRequestException; import org.hisp.dhis.feedback.ForbiddenException; import org.hisp.dhis.feedback.NotFoundException; import org.hisp.dhis.organisationunit.OrganisationUnit; @@ -50,9 +50,7 @@ import org.hisp.dhis.trackedentity.TrackedEntity; import org.hisp.dhis.tracker.acl.TrackerAccessManager; import org.hisp.dhis.tracker.export.Order; -import org.hisp.dhis.tracker.export.enrollment.EnrollmentService; -import org.hisp.dhis.tracker.export.event.EventService; -import org.hisp.dhis.tracker.export.trackedentity.TrackedEntityService; +import org.hisp.dhis.user.SystemUser; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -69,13 +67,9 @@ class RelationshipOperationParamsMapperTest extends TestBase { private static final UID EV_UID = UID.of("TvjwTPToKHO"); - @Mock private TrackedEntityService trackedEntityService; + @Mock private RelationshipStore relationshipStore; - @Mock private EnrollmentService enrollmentService; - - @Mock private EventService eventService; - - @Mock private TrackerAccessManager accessManager; + @Mock private TrackerAccessManager trackerAccessManager; @InjectMocks private RelationshipOperationParamsMapper mapper; @@ -97,12 +91,13 @@ public void setUp() { enrollment.setUid(EN_UID.getValue()); event = createEvent(programStage, enrollment, organisationUnit); event.setUid(EV_UID.getValue()); + injectSecurityContextNoSettings(new SystemUser()); } @Test void shouldMapTrackedEntityWhenATrackedEntityIsPassed() - throws NotFoundException, ForbiddenException, BadRequestException { - when(trackedEntityService.getTrackedEntity(TE_UID)).thenReturn(trackedEntity); + throws NotFoundException, ForbiddenException { + when(relationshipStore.findTrackedEntity(TE_UID)).thenReturn(Optional.of(trackedEntity)); RelationshipOperationParams params = RelationshipOperationParams.builder().type(TRACKED_ENTITY).identifier(TE_UID).build(); @@ -113,9 +108,8 @@ void shouldMapTrackedEntityWhenATrackedEntityIsPassed() } @Test - void shouldMapEnrollmentWhenAEnrollmentIsPassed() - throws NotFoundException, ForbiddenException, BadRequestException { - when(enrollmentService.getEnrollment(EN_UID)).thenReturn(enrollment); + void shouldMapEnrollmentWhenAEnrollmentIsPassed() throws NotFoundException, ForbiddenException { + when(relationshipStore.findEnrollment(EN_UID)).thenReturn(Optional.of(enrollment)); RelationshipOperationParams params = RelationshipOperationParams.builder().type(ENROLLMENT).identifier(EN_UID).build(); @@ -126,9 +120,8 @@ void shouldMapEnrollmentWhenAEnrollmentIsPassed() } @Test - void shouldMapEventWhenAEventIsPassed() - throws NotFoundException, ForbiddenException, BadRequestException { - when(eventService.getEvent(EV_UID)).thenReturn(event); + void shouldMapEventWhenAEventIsPassed() throws NotFoundException, ForbiddenException { + when(relationshipStore.findEvent(EV_UID)).thenReturn(Optional.of(event)); RelationshipOperationParams params = RelationshipOperationParams.builder().type(EVENT).identifier(EV_UID).build(); @@ -139,9 +132,8 @@ void shouldMapEventWhenAEventIsPassed() } @Test - void shouldMapOrderInGivenOrder() - throws ForbiddenException, NotFoundException, BadRequestException { - when(trackedEntityService.getTrackedEntity(TE_UID)).thenReturn(trackedEntity); + void shouldMapOrderInGivenOrder() throws ForbiddenException, NotFoundException { + when(relationshipStore.findTrackedEntity(TE_UID)).thenReturn(Optional.of(trackedEntity)); RelationshipOperationParams operationParams = RelationshipOperationParams.builder() @@ -157,8 +149,8 @@ void shouldMapOrderInGivenOrder() @Test void shouldMapNullOrderingParamsWhenNoOrderingParamsAreSpecified() - throws ForbiddenException, NotFoundException, BadRequestException { - when(trackedEntityService.getTrackedEntity(TE_UID)).thenReturn(trackedEntity); + throws ForbiddenException, NotFoundException { + when(relationshipStore.findTrackedEntity(TE_UID)).thenReturn(Optional.of(trackedEntity)); RelationshipOperationParams operationParams = RelationshipOperationParams.builder().type(TRACKED_ENTITY).identifier(TE_UID).build(); diff --git a/dhis-2/dhis-test-web-api/src/test/java/org/hisp/dhis/webapi/controller/tracker/JsonAssertions.java b/dhis-2/dhis-test-web-api/src/test/java/org/hisp/dhis/webapi/controller/tracker/JsonAssertions.java index b006553f812e..aa145430cd11 100644 --- a/dhis-2/dhis-test-web-api/src/test/java/org/hisp/dhis/webapi/controller/tracker/JsonAssertions.java +++ b/dhis-2/dhis-test-web-api/src/test/java/org/hisp/dhis/webapi/controller/tracker/JsonAssertions.java @@ -39,6 +39,7 @@ import java.util.Set; import java.util.function.Function; import java.util.function.Predicate; +import org.hisp.dhis.common.UidObject; import org.hisp.dhis.jsontree.JsonArray; import org.hisp.dhis.jsontree.JsonList; import org.hisp.dhis.jsontree.JsonObject; @@ -124,16 +125,16 @@ public static void assertTrackedEntityWithinRelationshipItem( jsonTe.getTrackedEntityType(), "trackedEntityType UID"); assertEquals(expected.getOrganisationUnit().getUid(), jsonTe.getOrgUnit(), "orgUnit UID"); - assertTrue(jsonTe.getAttributes().isEmpty(), "attributes should be empty"); + assertFalse(jsonTe.getAttributes().isEmpty(), "attributes should be empty"); assertFalse( jsonTe.has("relationships"), "relationships is not returned within relationship items"); } - public static void assertHasOnlyUid(String expectedUid, String member, JsonObject json) { + public static void assertHasOnlyUid(UidObject expected, String member, JsonObject json) { JsonObject j = json.getObject(member); assertFalse(j.isEmpty(), member + " should not be empty"); assertHasOnlyMembers(j, member); - assertEquals(expectedUid, j.getString(member).string(), member + " UID"); + assertEquals(expected.getUid(), j.getString(member).string(), member + " UID"); } public static void assertEnrollmentWithinRelationship( @@ -149,7 +150,7 @@ public static void assertEnrollmentWithinRelationship( assertEquals(expected.getFollowup(), jsonEnrollment.getFollowUp(), "followUp"); assertEquals( expected.getOrganisationUnit().getUid(), jsonEnrollment.getOrgUnit(), "orgUnit UID"); - assertTrue(jsonEnrollment.getArray("events").isEmpty(), "events should be empty"); + assertFalse(jsonEnrollment.getArray("events").isEmpty(), "events should be empty"); assertFalse( jsonEnrollment.has("relationships"), "relationships is not returned within relationship items"); diff --git a/dhis-2/dhis-test-web-api/src/test/java/org/hisp/dhis/webapi/controller/tracker/export/relationship/RelationshipsExportControllerTest.java b/dhis-2/dhis-test-web-api/src/test/java/org/hisp/dhis/webapi/controller/tracker/export/relationship/RelationshipsExportControllerTest.java index 3e688ac04e41..d18df071a797 100644 --- a/dhis-2/dhis-test-web-api/src/test/java/org/hisp/dhis/webapi/controller/tracker/export/relationship/RelationshipsExportControllerTest.java +++ b/dhis-2/dhis-test-web-api/src/test/java/org/hisp/dhis/webapi/controller/tracker/export/relationship/RelationshipsExportControllerTest.java @@ -27,204 +27,175 @@ */ package org.hisp.dhis.webapi.controller.tracker.export.relationship; -import static org.hisp.dhis.test.utils.Assertions.assertIsEmpty; import static org.hisp.dhis.test.utils.Assertions.assertStartsWith; -import static org.hisp.dhis.webapi.controller.tracker.JsonAssertions.assertContainsAll; +import static org.hisp.dhis.webapi.controller.tracker.JsonAssertions.assertContains; import static org.hisp.dhis.webapi.controller.tracker.JsonAssertions.assertEnrollmentWithinRelationship; import static org.hisp.dhis.webapi.controller.tracker.JsonAssertions.assertEventWithinRelationshipItem; import static org.hisp.dhis.webapi.controller.tracker.JsonAssertions.assertFirstRelationship; import static org.hisp.dhis.webapi.controller.tracker.JsonAssertions.assertHasOnlyMembers; import static org.hisp.dhis.webapi.controller.tracker.JsonAssertions.assertHasOnlyUid; -import static org.hisp.dhis.webapi.controller.tracker.JsonAssertions.assertNoRelationships; import static org.hisp.dhis.webapi.controller.tracker.JsonAssertions.assertRelationship; import static org.hisp.dhis.webapi.controller.tracker.JsonAssertions.assertTrackedEntityWithinRelationshipItem; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; -import java.util.Date; -import java.util.LinkedHashSet; +import java.io.IOException; +import java.util.ArrayList; import java.util.List; -import java.util.Set; -import org.hisp.dhis.category.CategoryOptionCombo; -import org.hisp.dhis.category.CategoryService; +import java.util.Map; +import java.util.function.Supplier; +import org.hisp.dhis.common.IdentifiableObject; import org.hisp.dhis.common.IdentifiableObjectManager; -import org.hisp.dhis.dataelement.DataElement; -import org.hisp.dhis.eventdatavalue.EventDataValue; +import org.hisp.dhis.dxf2.metadata.objectbundle.ObjectBundle; +import org.hisp.dhis.dxf2.metadata.objectbundle.ObjectBundleMode; +import org.hisp.dhis.dxf2.metadata.objectbundle.ObjectBundleParams; +import org.hisp.dhis.dxf2.metadata.objectbundle.ObjectBundleService; +import org.hisp.dhis.dxf2.metadata.objectbundle.ObjectBundleValidationService; +import org.hisp.dhis.dxf2.metadata.objectbundle.feedback.ObjectBundleValidationReport; import org.hisp.dhis.http.HttpStatus; +import org.hisp.dhis.importexport.ImportStrategy; import org.hisp.dhis.jsontree.JsonList; -import org.hisp.dhis.jsontree.JsonObject; -import org.hisp.dhis.note.Note; -import org.hisp.dhis.organisationunit.OrganisationUnit; import org.hisp.dhis.program.Enrollment; -import org.hisp.dhis.program.EnrollmentStatus; import org.hisp.dhis.program.Event; -import org.hisp.dhis.program.Program; -import org.hisp.dhis.program.ProgramStage; import org.hisp.dhis.relationship.Relationship; -import org.hisp.dhis.relationship.RelationshipConstraint; -import org.hisp.dhis.relationship.RelationshipEntity; -import org.hisp.dhis.relationship.RelationshipItem; -import org.hisp.dhis.relationship.RelationshipType; -import org.hisp.dhis.security.acl.AccessStringHelper; +import org.hisp.dhis.render.RenderFormat; +import org.hisp.dhis.render.RenderService; import org.hisp.dhis.test.webapi.PostgresControllerIntegrationTestBase; import org.hisp.dhis.trackedentity.TrackedEntity; -import org.hisp.dhis.trackedentity.TrackedEntityAttribute; -import org.hisp.dhis.trackedentity.TrackedEntityProgramOwner; -import org.hisp.dhis.trackedentity.TrackedEntityType; -import org.hisp.dhis.trackedentity.TrackedEntityTypeAttribute; -import org.hisp.dhis.trackedentityattributevalue.TrackedEntityAttributeValue; -import org.hisp.dhis.trackerdataview.TrackerDataView; +import org.hisp.dhis.tracker.imports.TrackerImportParams; +import org.hisp.dhis.tracker.imports.TrackerImportService; +import org.hisp.dhis.tracker.imports.domain.TrackerObjects; +import org.hisp.dhis.tracker.imports.report.ImportReport; +import org.hisp.dhis.tracker.imports.report.Status; +import org.hisp.dhis.tracker.imports.report.ValidationReport; import org.hisp.dhis.user.User; -import org.hisp.dhis.user.sharing.UserAccess; -import org.hisp.dhis.webapi.controller.tracker.JsonAttribute; -import org.hisp.dhis.webapi.controller.tracker.JsonDataValue; import org.hisp.dhis.webapi.controller.tracker.JsonNote; -import org.hisp.dhis.webapi.controller.tracker.JsonProgramOwner; import org.hisp.dhis.webapi.controller.tracker.JsonRelationship; -import org.hisp.dhis.webapi.controller.tracker.JsonRelationshipItem; -import org.hisp.dhis.webapi.controller.tracker.JsonUser; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.ClassPathResource; import org.springframework.transaction.annotation.Transactional; @Transactional +@TestInstance(TestInstance.Lifecycle.PER_CLASS) class RelationshipsExportControllerTest extends PostgresControllerIntegrationTestBase { + @Autowired private RenderService renderService; - @Autowired private IdentifiableObjectManager manager; - - @Autowired private CategoryService categoryService; - - private CategoryOptionCombo coc; - - private OrganisationUnit orgUnit; - - private OrganisationUnit anotherOrgUnit; - - private Program program; - - private ProgramStage programStage; - - private User owner; - - private User user; + @Autowired private ObjectBundleService objectBundleService; - private TrackedEntityType trackedEntityType; + @Autowired private ObjectBundleValidationService objectBundleValidationService; - private TrackedEntityAttribute tea; + @Autowired private TrackerImportService trackerImportService; - private TrackedEntityAttribute tea2; + @Autowired private IdentifiableObjectManager manager; - private DataElement dataElement; + private User importUser; + + private Event relationship1To; + private Relationship relationship1; + private TrackedEntity relationship1From; + private Relationship relationship2; + private TrackedEntity relationship2From; + private Enrollment relationship2To; + + protected ObjectBundle setUpMetadata(String path) throws IOException { + Map, List> metadata = + renderService.fromMetadata(new ClassPathResource(path).getInputStream(), RenderFormat.JSON); + ObjectBundleParams params = new ObjectBundleParams(); + params.setObjectBundleMode(ObjectBundleMode.COMMIT); + params.setImportStrategy(ImportStrategy.CREATE); + params.setObjects(metadata); + ObjectBundle bundle = objectBundleService.create(params); + assertNoErrors(objectBundleValidationService.validate(bundle)); + objectBundleService.commit(bundle); + return bundle; + } + + protected TrackerObjects fromJson(String path) throws IOException { + return renderService.fromJson( + new ClassPathResource(path).getInputStream(), TrackerObjects.class); + } + + @BeforeAll + void setUp() throws IOException { + setUpMetadata("tracker/simple_metadata.json"); + + importUser = userService.getUser("tTgjgobT1oS"); + injectSecurityContextUser(importUser); + + TrackerImportParams params = TrackerImportParams.builder().build(); + assertNoErrors( + trackerImportService.importTracker(params, fromJson("tracker/event_and_enrollment.json"))); + + manager.flush(); + manager.clear(); + + relationship1 = get(Relationship.class, "oLT07jKRu9e"); + relationship1From = relationship1.getFrom().getTrackedEntity(); + assertNotNull(relationship1From, "test expects 'from' to be a tracked entity"); + relationship1To = relationship1.getTo().getEvent(); + assertNotNull(relationship1To, "test expects 'to' to be an event"); + + relationship2 = get(Relationship.class, "p53a6314631"); + relationship2From = relationship2.getFrom().getTrackedEntity(); + assertNotNull(relationship2From, "test expects 'from' to be a tracked entity"); + relationship2To = relationship2.getTo().getEnrollment(); + assertNotNull(relationship2To, "test expects 'to' to be an enrollment"); + // for some reason we get a LazyInit exception in an assertion when running all tests if we + // don't eagerly fetch like we do here + relationship2From.getUid(); + relationship2To.getUid(); + relationship2.getRelationshipType().getUid(); + } @BeforeEach - void setUp() { - owner = makeUser("o"); - manager.save(owner, false); - - coc = categoryService.getDefaultCategoryOptionCombo(); - - orgUnit = createOrganisationUnit('A'); - orgUnit.getSharing().setOwner(owner); - manager.save(orgUnit, false); - - anotherOrgUnit = createOrganisationUnit('B'); - anotherOrgUnit.getSharing().setOwner(owner); - manager.save(anotherOrgUnit, false); - - user = createAndAddUser("tester", orgUnit); - user.setTeiSearchOrganisationUnits(Set.of(orgUnit)); - this.userService.updateUser(user); - - tea = createTrackedEntityAttribute('A'); - tea.getSharing().setOwner(owner); - tea.getSharing().addUserAccess(userAccess()); - manager.save(tea, false); - - tea2 = createTrackedEntityAttribute('B'); - tea2.getSharing().setOwner(owner); - tea2.getSharing().addUserAccess(userAccess()); - manager.save(tea2, false); - - trackedEntityType = trackedEntityTypeAccessible(); - - TrackedEntityTypeAttribute trackedEntityTypeAttribute = - new TrackedEntityTypeAttribute(trackedEntityType, tea); - trackedEntityTypeAttribute.setMandatory(false); - trackedEntityTypeAttribute.getSharing().setOwner(owner); - trackedEntityTypeAttribute.getSharing().addUserAccess(userAccess()); - manager.save(trackedEntityTypeAttribute); - - trackedEntityType.setTrackedEntityTypeAttributes(List.of(trackedEntityTypeAttribute)); - manager.save(trackedEntityType, false); - - program = createProgram('A'); - program.addOrganisationUnit(orgUnit); - program.getSharing().setOwner(owner); - program.getSharing().addUserAccess(userAccess()); - program.setTrackedEntityType(trackedEntityType); - manager.save(program, false); - - programStage = createProgramStage('A', program); - programStage.getSharing().setOwner(owner); - programStage.getSharing().addUserAccess(userAccess()); - manager.save(programStage, false); - - dataElement = createDataElement('A'); - manager.save(dataElement, false); + void setUpUser() { + switchContextToUser(importUser); } @Test void getRelationshipsById() { - TrackedEntity to = trackedEntity(); - Event from = event(enrollment(to)); - Relationship r = relationship(from, to); - switchContextToUser(user); - - JsonRelationship relationship = - GET("/tracker/relationships/{uid}", r.getUid()) + JsonRelationship jsonRelationship = + GET("/tracker/relationships/{uid}", relationship1.getUid()) .content(HttpStatus.OK) .as(JsonRelationship.class); assertHasOnlyMembers( - relationship, "relationship", "relationshipType", "createdAtClient", "from", "to"); - assertRelationship(r, relationship); - assertHasOnlyUid(from.getUid(), "event", relationship.getObject("from")); - assertHasOnlyUid(to.getUid(), "trackedEntity", relationship.getObject("to")); + jsonRelationship, "relationship", "relationshipType", "createdAtClient", "from", "to"); + assertRelationship(relationship1, jsonRelationship); + assertHasOnlyUid(relationship1From, "trackedEntity", jsonRelationship.getObject("from")); + assertHasOnlyUid(relationship1To, "event", jsonRelationship.getObject("to")); } @Test void getRelationshipsByIdWithFieldsAll() { - TrackedEntity to = trackedEntity(); - Event from = event(enrollment(to)); - Relationship r = relationship(from, to); - switchContextToUser(user); - - JsonRelationship relationship = - GET("/tracker/relationships/{uid}?fields=*", r.getUid()) + JsonRelationship jsonRelationship = + GET("/tracker/relationships/{uid}?fields=*", relationship1.getUid()) .content(HttpStatus.OK) .as(JsonRelationship.class); - assertRelationship(r, relationship); - assertEventWithinRelationshipItem(from, relationship.getFrom()); - assertTrackedEntityWithinRelationshipItem(to, relationship.getTo()); + assertRelationship(relationship1, jsonRelationship); + assertTrackedEntityWithinRelationshipItem(relationship1From, jsonRelationship.getFrom()); + assertEventWithinRelationshipItem(relationship1To, jsonRelationship.getTo()); } @Test void getRelationshipsByIdWithFields() { - TrackedEntity to = trackedEntity(); - Event from = event(enrollment(to)); - Relationship r = relationship(from, to); - switchContextToUser(user); - - JsonRelationship relationship = - GET("/tracker/relationships/{uid}?fields=relationship,from[event]", r.getUid()) + JsonRelationship jsonRelationship = + GET("/tracker/relationships/{uid}?fields=relationship,to[event]", relationship1.getUid()) .content(HttpStatus.OK) .as(JsonRelationship.class); - assertHasOnlyMembers(relationship, "relationship", "from"); - assertEquals(r.getUid(), relationship.getRelationship(), "relationship UID"); - assertHasOnlyMembers(relationship.getObject("from"), "event"); - assertEquals(from.getUid(), relationship.getFrom().getEvent().getEvent(), "event UID"); + assertHasOnlyMembers(jsonRelationship, "relationship", "to"); + assertEquals(relationship1.getUid(), jsonRelationship.getRelationship(), "relationship UID"); + assertHasOnlyMembers(jsonRelationship.getObject("to"), "event"); + assertEquals( + relationship1To.getUid(), jsonRelationship.getTo().getEvent().getEvent(), "event UID"); } @Test @@ -252,132 +223,132 @@ void getRelationshipsBadRequestWithMultipleParams() { @Test void getRelationshipsByEvent() { - TrackedEntity to = trackedEntity(); - Event from = event(enrollment(to)); - Relationship r = relationship(from, to); - switchContextToUser(user); - - JsonList relationships = - GET("/tracker/relationships?event={uid}", from.getUid()) + JsonList jsonRelationships = + GET("/tracker/relationships?event={uid}", relationship1To.getUid()) .content(HttpStatus.OK) .getList("relationships", JsonRelationship.class); - JsonObject relationship = assertFirstRelationship(r, relationships); - assertHasOnlyMembers( - relationship, "relationship", "relationshipType", "createdAtClient", "from", "to"); - assertHasOnlyUid(from.getUid(), "event", relationship.getObject("from")); - assertHasOnlyUid(to.getUid(), "trackedEntity", relationship.getObject("to")); + JsonRelationship jsonRelationship = + assertContains( + jsonRelationships, + rel -> relationship1.getUid().equals(rel.getRelationship()), + "expected to find relationship " + relationship1.getUid()); + + assertRelationship(relationship1, jsonRelationship); + assertHasOnlyUid(relationship1From, "trackedEntity", jsonRelationship.getFrom()); + assertHasOnlyUid(relationship1To, "event", jsonRelationship.getTo()); } @Test void getRelationshipsByEventWithAllFields() { - TrackedEntity to = trackedEntity(); - Event from = event(enrollment(to)); - Relationship r = relationship(from, to); - switchContextToUser(user); - - JsonList relationships = - GET("/tracker/relationships?event={uid}&fields=*", from.getUid()) + JsonList jsonRelationships = + GET("/tracker/relationships?event={uid}&fields=*", relationship1To.getUid()) .content(HttpStatus.OK) .getList("relationships", JsonRelationship.class); - JsonRelationship relationship = assertFirstRelationship(r, relationships); - assertEventWithinRelationshipItem(from, relationship.getFrom()); - assertTrackedEntityWithinRelationshipItem(to, relationship.getTo()); + JsonRelationship jsonRelationship = + assertContains( + jsonRelationships, + rel -> relationship1.getUid().equals(rel.getRelationship()), + "expected to find relationship " + relationship1.getUid()); + + assertRelationship(relationship1, jsonRelationship); + assertTrackedEntityWithinRelationshipItem(relationship1From, jsonRelationship.getFrom()); + assertEventWithinRelationshipItem(relationship1To, jsonRelationship.getTo()); } @Test void getRelationshipsByEventWithFields() { - TrackedEntity to = trackedEntity(); - Event from = event(enrollment(to)); - Relationship r = relationship(from, to); - switchContextToUser(user); - - JsonList relationships = - GET("/tracker/relationships?event={uid}&fields=relationship,from[event]", from.getUid()) + JsonList jsonRelationships = + GET( + "/tracker/relationships?event={uid}&fields=relationship,to[event]", + relationship1To.getUid()) .content(HttpStatus.OK) .getList("relationships", JsonRelationship.class); - assertEquals(1, relationships.size(), "one relationship expected"); - JsonRelationship relationship = relationships.get(0).as(JsonRelationship.class); - assertHasOnlyMembers(relationship, "relationship", "from"); - assertEquals(r.getUid(), relationship.getRelationship(), "relationship UID"); - assertHasOnlyMembers(relationship.getObject("from"), "event"); - assertEquals(from.getUid(), relationship.getFrom().getEvent().getEvent(), "event UID"); - } + JsonRelationship jsonRelationship = + assertContains( + jsonRelationships, + rel -> relationship1.getUid().equals(rel.getRelationship()), + "expected to find relationship " + relationship1.getUid()); - @Test - void getRelationshipsByEventWithAssignedUser() { - TrackedEntity to = trackedEntity(); - Event from = event(enrollment(to)); - from.setAssignedUser(owner); - relationship(from, to); - switchContextToUser(user); - - JsonList relationships = - GET("/tracker/relationships?event={uid}&fields=from[event[assignedUser]]", from.getUid()) - .content(HttpStatus.OK) - .getList("relationships", JsonRelationship.class); - - JsonUser user = relationships.get(0).getFrom().getEvent().getAssignedUser(); - assertEquals(owner.getUid(), user.getUid()); - assertEquals(owner.getUsername(), user.getUsername()); - } + assertHasOnlyMembers(jsonRelationship, "relationship", "to"); + assertHasOnlyMembers(jsonRelationship.getTo(), "event"); + assertEquals( + relationship1To.getUid(), jsonRelationship.getTo().getEvent().getEvent(), "event UID"); + } + + // TODO(DHIS2-18883) migrate these tests + // @Test + // void getRelationshipsByEventWithAssignedUser() { + // JsonList relationships = + // GET("/tracker/relationships?event={uid}&fields=from[event[assignedUser]]", + // from.getUid()) + // .content(HttpStatus.OK) + // .getList("relationships", JsonRelationship.class); + // + // JsonUser user = relationships.get(0).getFrom().getEvent().getAssignedUser(); + // assertEquals(owner.getUid(), user.getUid()); + // assertEquals(owner.getUsername(), user.getUsername()); + // } + // @Test + // void getRelationshipsByEventWithDataValues() { + // TrackedEntity to = trackedEntity(); + // Event from = event(enrollment(to)); + // from.setEventDataValues(Set.of(new EventDataValue(dataElement.getUid(), "12"))); + // Relationship relationship = relationship(from, to); + // RelationshipType type = relationship.getRelationshipType(); + // + // RelationshipConstraint toConstraint = new RelationshipConstraint(); + // + // TrackerDataView trackerDataView = new TrackerDataView(); + // trackerDataView.setDataElements(new LinkedHashSet<>(Set.of(dataElement.getUid()))); + // + // toConstraint.setTrackerDataView(trackerDataView); + // + // type.setFromConstraint(toConstraint); + // + // manager.update(type); + // switchContextToUser(user); + // + // JsonList relationships = + // GET( + // + // "/tracker/relationships?event={uid}&fields=from[event[dataValues[dataElement,value]]]", + // from.getUid()) + // .content(HttpStatus.OK) + // .getList("relationships", JsonRelationship.class); + // + // JsonDataValue dataValue = relationships.get(0).getFrom().getEvent().getDataValues().get(0); + // assertEquals(dataElement.getUid(), dataValue.getDataElement()); + // assertEquals("12", dataValue.getValue()); + // } @Test - void getRelationshipsByEventWithDataValues() { - TrackedEntity to = trackedEntity(); - Event from = event(enrollment(to)); - from.setEventDataValues(Set.of(new EventDataValue(dataElement.getUid(), "12"))); - Relationship relationship = relationship(from, to); - RelationshipType type = relationship.getRelationshipType(); - - RelationshipConstraint toConstraint = new RelationshipConstraint(); - - TrackerDataView trackerDataView = new TrackerDataView(); - trackerDataView.setDataElements(new LinkedHashSet<>(Set.of(dataElement.getUid()))); - - toConstraint.setTrackerDataView(trackerDataView); - - type.setFromConstraint(toConstraint); - - manager.update(type); - switchContextToUser(user); - - JsonList relationships = + void getRelationshipsByEventWithNotes() { + JsonList jsonRelationships = GET( - "/tracker/relationships?event={uid}&fields=from[event[dataValues[dataElement,value]]]", - from.getUid()) + "/tracker/relationships?event={uid}&fields=relationship,to[event[notes]]", + relationship1To.getUid()) .content(HttpStatus.OK) .getList("relationships", JsonRelationship.class); - JsonDataValue dataValue = relationships.get(0).getFrom().getEvent().getDataValues().get(0); - assertEquals(dataElement.getUid(), dataValue.getDataElement()); - assertEquals("12", dataValue.getValue()); - } + JsonRelationship jsonRelationship = + assertContains( + jsonRelationships, + rel -> relationship1.getUid().equals(rel.getRelationship()), + "expected to find relationship " + relationship1.getUid()); - @Test - void getRelationshipsByEventWithNotes() { - TrackedEntity to = trackedEntity(); - Event from = event(enrollment(to)); - from.setNotes(List.of(note("oqXG28h988k", "my notes", owner.getUid()))); - relationship(from, to); - switchContextToUser(user); - - JsonList relationships = - GET("/tracker/relationships?event={uid}&fields=from[event[notes]]", from.getUid()) - .content(HttpStatus.OK) - .getList("relationships", JsonRelationship.class); - - JsonNote note = relationships.get(0).getFrom().getEvent().getNotes().get(0); - assertEquals("oqXG28h988k", note.getNote()); - assertEquals("my notes", note.getValue()); - assertEquals(owner.getUid(), note.getStoredBy()); + JsonList notes = jsonRelationship.getTo().getEvent().getNotes(); + notes.forEach( + note -> { + assertHasOnlyMembers(note, "note", "value", "storedAt", "storedBy", "createdBy"); + }); } @Test void getRelationshipsByEventNotFound() { - switchContextToUser(user); + assertNull(manager.get(Event.class, "Hq3Kc6HK4OZ"), "test expects event not to exist"); assertStartsWith( "Event with id Hq3Kc6HK4OZ", @@ -386,114 +357,110 @@ void getRelationshipsByEventNotFound() { @Test void getRelationshipsByEnrollment() { - TrackedEntity to = trackedEntity(); - Enrollment from = enrollment(to); - Relationship r = relationship(from, to); - switchContextToUser(user); - - JsonList relationships = - GET("/tracker/relationships?enrollment=" + from.getUid()) + JsonList jsonRelationships = + GET("/tracker/relationships?enrollment=" + relationship2To.getUid()) .content(HttpStatus.OK) .getList("relationships", JsonRelationship.class); - JsonObject relationship = assertFirstRelationship(r, relationships); - assertHasOnlyMembers(relationship, "relationship", "relationshipType", "from", "to"); - assertHasOnlyUid(from.getUid(), "enrollment", relationship.getObject("from")); - assertHasOnlyUid(to.getUid(), "trackedEntity", relationship.getObject("to")); + JsonRelationship jsonRelationship = assertFirstRelationship(relationship2, jsonRelationships); + assertHasOnlyMembers(jsonRelationship, "relationship", "relationshipType", "from", "to"); + assertHasOnlyUid(relationship2From, "trackedEntity", jsonRelationship.getFrom()); + assertHasOnlyUid(relationship2To, "enrollment", jsonRelationship.getTo()); } @Test void getRelationshipsByEnrollmentWithFieldsAll() { - TrackedEntity to = trackedEntity(); - Enrollment from = enrollment(to); - Relationship r = relationship(from, to); - switchContextToUser(user); - - JsonList relationships = - GET("/tracker/relationships?enrollment={uid}&fields=*", from.getUid()) - .content(HttpStatus.OK) - .getList("relationships", JsonRelationship.class); - - JsonRelationship relationship = assertFirstRelationship(r, relationships); - assertEnrollmentWithinRelationship(from, relationship.getFrom()); - assertTrackedEntityWithinRelationshipItem(to, relationship.getTo()); - } - - @Test - void getRelationshipsByEnrollmentWithEvents() { - Enrollment from = enrollment(trackedEntity()); - Event to = event(from); - relationship(from, to); - switchContextToUser(user); - - JsonList relationships = - GET( - "/tracker/relationships?enrollment={uid}&fields=from[enrollment[events[enrollment,event]]]", - from.getUid()) + JsonList jsonRelationships = + GET("/tracker/relationships?enrollment={uid}&fields=*", relationship2To.getUid()) .content(HttpStatus.OK) .getList("relationships", JsonRelationship.class); - JsonRelationshipItem.JsonEvent event = - relationships.get(0).getFrom().getEnrollment().getEvents().get(0); - assertEquals(from.getUid(), event.getEnrollment()); - assertEquals(to.getUid(), event.getEvent()); - } - - @Test - void getRelationshipsByEnrollmentWithAttributes() { - TrackedEntity to = trackedEntity(); - to.setTrackedEntityAttributeValues(Set.of(attributeValue(tea, to, "12"))); - program.setProgramAttributes(List.of(createProgramTrackedEntityAttribute(program, tea))); - - Enrollment from = enrollment(to); - Relationship relationship = relationship(from, to); - - RelationshipType type = relationship.getRelationshipType(); - - RelationshipConstraint constraint = new RelationshipConstraint(); - - TrackerDataView trackerDataView = new TrackerDataView(); - trackerDataView.setAttributes(new LinkedHashSet<>(Set.of(tea.getUid()))); - - constraint.setTrackerDataView(trackerDataView); - - type.setFromConstraint(constraint); - switchContextToUser(user); - - JsonList relationships = - GET( - "/tracker/relationships?enrollment={uid}&fields=from[enrollment[attributes[attribute,value]]]", - from.getUid()) - .content(HttpStatus.OK) - .getList("relationships", JsonRelationship.class); - - JsonAttribute attribute = relationships.get(0).getFrom().getEnrollment().getAttributes().get(0); - assertEquals(tea.getUid(), attribute.getAttribute()); - assertEquals("12", attribute.getValue()); - } - - @Test - void getRelationshipsByEnrollmentWithNotes() { - TrackedEntity to = trackedEntity(); - Enrollment from = enrollment(to); - from.setNotes(List.of(note("oqXG28h988k", "my notes", owner.getUid()))); - relationship(from, to); - switchContextToUser(user); - - JsonList relationships = - GET("/tracker/relationships?enrollment={uid}&fields=from[enrollment[notes]]", from.getUid()) - .content(HttpStatus.OK) - .getList("relationships", JsonRelationship.class); - - JsonNote note = relationships.get(0).getFrom().getEnrollment().getNotes().get(0); - assertEquals("oqXG28h988k", note.getNote()); - assertEquals("my notes", note.getValue()); - assertEquals(owner.getUid(), note.getStoredBy()); - } + JsonRelationship jsonRelationship = assertFirstRelationship(relationship2, jsonRelationships); + assertTrackedEntityWithinRelationshipItem(relationship2From, jsonRelationship.getFrom()); + assertEnrollmentWithinRelationship(relationship2To, jsonRelationship.getTo()); + } + + // TODO(DHIS2-18883) migrate these tests + // @Test + // void getRelationshipsByEnrollmentWithEvents() { + // Enrollment from = enrollment(trackedEntity()); + // Event to = event(from); + // relationship(from, to); + // switchContextToUser(user); + // + // JsonList relationships = + // GET( + // + // "/tracker/relationships?enrollment={uid}&fields=from[enrollment[events[enrollment,event]]]", + // from.getUid()) + // .content(HttpStatus.OK) + // .getList("relationships", JsonRelationship.class); + // + // JsonRelationshipItem.JsonEvent event = + // relationships.get(0).getFrom().getEnrollment().getEvents().get(0); + // assertEquals(from.getUid(), event.getEnrollment()); + // assertEquals(to.getUid(), event.getEvent()); + // } + // + // @Test + // void getRelationshipsByEnrollmentWithAttributes() { + // TrackedEntity to = trackedEntity(); + // to.setTrackedEntityAttributeValues(Set.of(attributeValue(tea, to, "12"))); + // program.setProgramAttributes(List.of(createProgramTrackedEntityAttribute(program, tea))); + // + // Enrollment from = enrollment(to); + // Relationship relationship = relationship(from, to); + // + // RelationshipType type = relationship.getRelationshipType(); + // + // RelationshipConstraint constraint = new RelationshipConstraint(); + // + // TrackerDataView trackerDataView = new TrackerDataView(); + // trackerDataView.setAttributes(new LinkedHashSet<>(Set.of(tea.getUid()))); + // + // constraint.setTrackerDataView(trackerDataView); + // + // type.setFromConstraint(constraint); + // switchContextToUser(user); + // + // JsonList relationships = + // GET( + // + // "/tracker/relationships?enrollment={uid}&fields=from[enrollment[attributes[attribute,value]]]", + // from.getUid()) + // .content(HttpStatus.OK) + // .getList("relationships", JsonRelationship.class); + // + // JsonAttribute attribute = + // relationships.get(0).getFrom().getEnrollment().getAttributes().get(0); + // assertEquals(tea.getUid(), attribute.getAttribute()); + // assertEquals("12", attribute.getValue()); + // } + // + // @Test + // void getRelationshipsByEnrollmentWithNotes() { + // TrackedEntity to = trackedEntity(); + // Enrollment from = enrollment(to); + // from.setNotes(List.of(note("oqXG28h988k", "my notes", owner.getUid()))); + // relationship(from, to); + // switchContextToUser(user); + // + // JsonList relationships = + // GET("/tracker/relationships?enrollment={uid}&fields=from[enrollment[notes]]", + // from.getUid()) + // .content(HttpStatus.OK) + // .getList("relationships", JsonRelationship.class); + // + // JsonNote note = relationships.get(0).getFrom().getEnrollment().getNotes().get(0); + // assertEquals("oqXG28h988k", note.getNote()); + // assertEquals("my notes", note.getValue()); + // assertEquals(owner.getUid(), note.getStoredBy()); + // } @Test void getRelationshipsByEnrollmentNotFound() { - switchContextToUser(user); + assertNull(manager.get(Enrollment.class, "Hq3Kc6HK4OZ"), "test expects event not to exist"); + assertStartsWith( "Enrollment with id Hq3Kc6HK4OZ", GET("/tracker/relationships?enrollment=Hq3Kc6HK4OZ") @@ -503,555 +470,372 @@ void getRelationshipsByEnrollmentNotFound() { @Test void getRelationshipsByTrackedEntity() { - TrackedEntity to = trackedEntity(); - Enrollment from = enrollment(to); - Relationship r = relationship(from, to); - switchContextToUser(user); - - JsonList relationships = - GET("/tracker/relationships?trackedEntity={trackedEntity}", to.getUid()) - .content(HttpStatus.OK) - .getList("relationships", JsonRelationship.class); - - JsonObject relationship = assertFirstRelationship(r, relationships); - assertHasOnlyMembers(relationship, "relationship", "relationshipType", "from", "to"); - assertHasOnlyUid(from.getUid(), "enrollment", relationship.getObject("from")); - assertHasOnlyUid(to.getUid(), "trackedEntity", relationship.getObject("to")); - } - - @Test - void shouldNotGetRelationshipsByTrackedEntityWhenRelationshipIsDeleted() { - TrackedEntity to = trackedEntity(); - Enrollment from = enrollment(to); - Relationship r = relationship(from, to); - - r.setDeleted(true); - manager.update(r); - switchContextToUser(user); - - assertNoRelationships( - GET("/tracker/relationships?trackedEntity={te}", to.getUid()).content(HttpStatus.OK)); - } - - @Test - void shouldNotGetRelationshipsByEnrollmentWhenRelationshipIsDeleted() { - TrackedEntity to = trackedEntity(); - Enrollment from = enrollment(to); - Relationship r = relationship(from, to); - - r.setDeleted(true); - manager.update(r); - switchContextToUser(user); - - assertNoRelationships( - GET("/tracker/relationships?enrollment={en}", from.getUid()).content(HttpStatus.OK)); - } - - @Test - void shouldNotGetRelationshipsByEventWhenRelationshipIsDeleted() { - TrackedEntity to = trackedEntity(); - Event from = event(enrollment(to)); - Relationship r = relationship(from, to); - - r.setDeleted(true); - manager.update(r); - switchContextToUser(user); - - assertNoRelationships( - GET("/tracker/relationships?event={ev}", from.getUid()).content(HttpStatus.OK)); - } - - @Test - void shouldGetRelationshipsByTrackedEntityWhenRelationshipIsDeleted() { - TrackedEntity to = trackedEntity(); - Enrollment from = enrollment(to); - Relationship r = relationship(from, to); - - r.setDeleted(true); - manager.update(r); - switchContextToUser(user); - - JsonList relationships = - GET("/tracker/relationships?trackedEntity={te}&includeDeleted=true", to.getUid()) - .content(HttpStatus.OK) - .getList("relationships", JsonRelationship.class); - - assertFirstRelationship(r, relationships); - } - - @Test - void shouldGetRelationshipsByEventWhenRelationshipIsDeleted() { - TrackedEntity to = trackedEntity(); - Event from = event(enrollment(to)); - Relationship r = relationship(from, to); - - r.setDeleted(true); - manager.update(r); - switchContextToUser(user); - - JsonList relationships = - GET("/tracker/relationships?event={ev}&includeDeleted=true", from.getUid()) - .content(HttpStatus.OK) - .getList("relationships", JsonRelationship.class); - - assertFirstRelationship(r, relationships); - } - - @Test - void shouldGetRelationshipsByEnrollmentWhenRelationshipIsDeleted() { - TrackedEntity to = trackedEntity(); - Enrollment from = enrollment(to); - Relationship r = relationship(from, to); - - r.setDeleted(true); - manager.update(r); - switchContextToUser(user); - - JsonList relationships = - GET("/tracker/relationships?enrollment={en}&includeDeleted=true", from.getUid()) - .content(HttpStatus.OK) - .getList("relationships", JsonRelationship.class); - - assertFirstRelationship(r, relationships); - } - - @Test - void getRelationshipsByDeprecatedTei() { - TrackedEntity to = trackedEntity(); - Enrollment from = enrollment(to); - Relationship r = relationship(from, to); - switchContextToUser(user); - - JsonList relationships = - GET("/tracker/relationships?tei=" + to.getUid()) - .content(HttpStatus.OK) - .getList("relationships", JsonRelationship.class); - - JsonObject relationship = assertFirstRelationship(r, relationships); - assertHasOnlyMembers(relationship, "relationship", "relationshipType", "from", "to"); - assertHasOnlyUid(from.getUid(), "enrollment", relationship.getObject("from")); - assertHasOnlyUid(to.getUid(), "trackedEntity", relationship.getObject("to")); - } - - @Test - void getRelationshipsByTrackedEntityWithEnrollments() { - TrackedEntity to = trackedEntity(); - Enrollment from = enrollment(to); - relationship(from, to); - switchContextToUser(user); - - JsonList relationships = - GET( - "/tracker/relationships?trackedEntity={trackedEntity}&fields=to[trackedEntity[enrollments[enrollment,trackedEntity]]", - to.getUid()) - .content(HttpStatus.OK) - .getList("relationships", JsonRelationship.class); - - JsonRelationshipItem.JsonEnrollment enrollment = - relationships.get(0).getTo().getTrackedEntity().getEnrollments().get(0); - assertEquals(from.getUid(), enrollment.getEnrollment()); - assertEquals(to.getUid(), enrollment.getTrackedEntity()); - } - - @Test - void getRelationshipsByTrackedEntityAndEnrollmentWithAttributesIsEmpty() { - // Tracked entity attribute values are owned by the tracked entity and only mapped onto the - // enrollment on export. Program tracked entity attributes are only returned by the underlying - // TE service if a program is - // provided which is not possible on the relationship endpoint. - TrackedEntity to = trackedEntity(orgUnit); - to.setTrackedEntityAttributeValues( - Set.of(attributeValue(tea, to, "12"), attributeValue(tea2, to, "24"))); - program.setProgramAttributes(List.of(createProgramTrackedEntityAttribute(program, tea2))); - Enrollment from = enrollment(to); - Relationship relationship = relationship(from, to); - - RelationshipType type = relationship.getRelationshipType(); - - RelationshipConstraint fromConstraint = new RelationshipConstraint(); - - TrackerDataView trackerDataView = new TrackerDataView(); - trackerDataView.setAttributes(new LinkedHashSet<>(Set.of(tea2.getUid()))); - - fromConstraint.setTrackerDataView(trackerDataView); - - RelationshipConstraint toConstraint = new RelationshipConstraint(); - - TrackerDataView dataView = new TrackerDataView(); - dataView.setAttributes(new LinkedHashSet<>(Set.of(tea.getUid(), tea2.getUid()))); - - toConstraint.setTrackerDataView(dataView); - - type.setFromConstraint(fromConstraint); - type.setToConstraint(toConstraint); - switchContextToUser(user); - - JsonList relationships = - GET( - "/tracker/relationships?trackedEntity={trackedEntity}&fields=from[enrollment[attributes[attribute,value]]],to[trackedEntity[attributes[attribute,value]]]", - to.getUid()) - .content(HttpStatus.OK) - .getList("relationships", JsonRelationship.class); - - JsonList enrollmentAttr = - relationships.get(0).getFrom().getEnrollment().getAttributes(); - assertIsEmpty( - enrollmentAttr.toList(JsonAttribute::getAttribute), - "program attributes should not be returned as no program can be provided"); - JsonList teAttributes = - relationships.get(0).getTo().getTrackedEntity().getAttributes(); - assertContainsAll(List.of(tea.getUid()), teAttributes, JsonAttribute::getAttribute); - assertContainsAll(List.of("12"), teAttributes, JsonAttribute::getValue); - } - - @Test - void getRelationshipsByTrackedEntityWithProgramOwners() { - TrackedEntity to = trackedEntity(orgUnit); - Enrollment from = enrollment(to); - to.setProgramOwners(Set.of(new TrackedEntityProgramOwner(to, from.getProgram(), orgUnit))); - relationship(from, to); - switchContextToUser(user); - - JsonList relationships = - GET( - "/tracker/relationships?trackedEntity={trackedEntity}&fields=to[trackedEntity[programOwners]", - to.getUid()) - .content(HttpStatus.OK) - .getList("relationships", JsonRelationship.class); - - JsonProgramOwner jsonProgramOwner = - relationships.get(0).getTo().getTrackedEntity().getProgramOwners().get(0); - assertEquals(orgUnit.getUid(), jsonProgramOwner.getOrgUnit()); - assertEquals(to.getUid(), jsonProgramOwner.getTrackedEntity()); - assertEquals(from.getProgram().getUid(), jsonProgramOwner.getProgram()); - } - - @Test - void getRelationshipsByTrackedEntityRelationshipTeToTe() { - TrackedEntity from = trackedEntity(); - TrackedEntity to = trackedEntity(); - Relationship r = relationship(from, to); - switchContextToUser(user); - - JsonList relationships = - GET("/tracker/relationships?trackedEntity={trackedEntity}", from.getUid()) - .content(HttpStatus.OK) - .getList("relationships", JsonRelationship.class); - - JsonObject relationship = assertFirstRelationship(r, relationships); - assertHasOnlyMembers(relationship, "relationship", "relationshipType", "from", "to"); - assertHasOnlyUid(from.getUid(), "trackedEntity", relationship.getObject("from")); - assertHasOnlyUid(to.getUid(), "trackedEntity", relationship.getObject("to")); - } - - @Test - void shouldRetrieveRelationshipWhenUserHasAccessToRelationship() { - TrackedEntity from = trackedEntity(); - TrackedEntity to = trackedEntity(); - Relationship r = relationship(from, to); - switchContextToUser(user); - - JsonList relationships = - GET("/tracker/relationships?trackedEntity={trackedEntity}", from.getUid()) + JsonList jsonRelationships = + GET("/tracker/relationships?trackedEntity={trackedEntity}", relationship1From.getUid()) .content(HttpStatus.OK) .getList("relationships", JsonRelationship.class); - JsonObject relationship = assertFirstRelationship(r, relationships); - assertHasOnlyMembers(relationship, "relationship", "relationshipType", "from", "to"); - assertHasOnlyUid(from.getUid(), "trackedEntity", relationship.getObject("from")); - assertHasOnlyUid(to.getUid(), "trackedEntity", relationship.getObject("to")); - } - - @Test - void getRelationshipsByTrackedEntityRelationshipsNoAccessToRelationshipType() { - TrackedEntity from = trackedEntity(); - TrackedEntity to = trackedEntity(); - relationship(relationshipTypeNotAccessible(), from, to); - switchContextToUser(user); - - assertNoRelationships( - GET("/tracker/relationships?trackedEntity={trackedEntity}", from.getUid()) - .content(HttpStatus.OK)); - } - - @Test - void shouldRetrieveNoRelationshipsWhenUserHasNoAccessToRelationshipItemTo() { - TrackedEntity from = trackedEntity(); - TrackedEntity to = trackedEntityNotInSearchScope(); - relationship(from, to); - switchContextToUser(user); - - assertNoRelationships( - GET("/tracker/relationships?trackedEntity={trackedEntity}", from.getUid()) - .content(HttpStatus.OK)); - } - - @Test - void shouldReturnForbiddenWhenUserHasNoAccessToRelationshipItemFrom() { - TrackedEntity from = trackedEntityNotInSearchScope(); - TrackedEntity to = trackedEntity(); - relationship(from, to); - switchContextToUser(user); - - assertEquals( - HttpStatus.FORBIDDEN, - GET("/tracker/relationships?trackedEntity={trackedEntity}", from.getUid()).status()); - } - - @Test - void - shouldReturnForbiddenWhenGetRelationshipsByTrackedEntityWithNotAccessibleTrackedEntityType() { - TrackedEntityType type = trackedEntityTypeNotAccessible(); - TrackedEntity from = trackedEntity(type); - TrackedEntity to = trackedEntity(type); - relationship(from, to); - switchContextToUser(user); + JsonRelationship jsonRelationship = + assertContains( + jsonRelationships, + rel -> relationship1.getUid().equals(rel.getRelationship()), + "expected to find relationship " + relationship1.getUid()); + assertRelationship(relationship1, jsonRelationship); + assertHasOnlyMembers( + jsonRelationship, "relationship", "relationshipType", "createdAtClient", "from", "to"); + assertHasOnlyUid(relationship1From, "trackedEntity", jsonRelationship.getFrom()); + assertHasOnlyUid(relationship1To, "event", jsonRelationship.getTo()); + } + + // + // @Test + // void shouldNotGetRelationshipsByTrackedEntityWhenRelationshipIsDeleted() { + // TrackedEntity to = trackedEntity(); + // Enrollment from = enrollment(to); + // Relationship r = relationship(from, to); + // + // r.setDeleted(true); + // manager.update(r); + // switchContextToUser(user); + // + // assertNoRelationships( + // GET("/tracker/relationships?trackedEntity={te}", to.getUid()).content(HttpStatus.OK)); + // } + // + // @Test + // void shouldNotGetRelationshipsByEnrollmentWhenRelationshipIsDeleted() { + // TrackedEntity to = trackedEntity(); + // Enrollment from = enrollment(to); + // Relationship r = relationship(from, to); + // + // r.setDeleted(true); + // manager.update(r); + // switchContextToUser(user); + // + // assertNoRelationships( + // GET("/tracker/relationships?enrollment={en}", from.getUid()).content(HttpStatus.OK)); + // } + // + // @Test + // void shouldNotGetRelationshipsByEventWhenRelationshipIsDeleted() { + // TrackedEntity to = trackedEntity(); + // Event from = event(enrollment(to)); + // Relationship r = relationship(from, to); + // + // r.setDeleted(true); + // manager.update(r); + // switchContextToUser(user); + // + // assertNoRelationships( + // GET("/tracker/relationships?event={ev}", from.getUid()).content(HttpStatus.OK)); + // } + // + // @Test + // void shouldGetRelationshipsByTrackedEntityWhenRelationshipIsDeleted() { + // TrackedEntity to = trackedEntity(); + // Enrollment from = enrollment(to); + // Relationship r = relationship(from, to); + // + // r.setDeleted(true); + // manager.update(r); + // switchContextToUser(user); + // + // JsonList relationships = + // GET("/tracker/relationships?trackedEntity={te}&includeDeleted=true", to.getUid()) + // .content(HttpStatus.OK) + // .getList("relationships", JsonRelationship.class); + // + // assertFirstRelationship(r, relationships); + // } + // + // @Test + // void shouldGetRelationshipsByEventWhenRelationshipIsDeleted() { + // TrackedEntity to = trackedEntity(); + // Event from = event(enrollment(to)); + // Relationship r = relationship(from, to); + // + // r.setDeleted(true); + // manager.update(r); + // switchContextToUser(user); + // + // JsonList relationships = + // GET("/tracker/relationships?event={ev}&includeDeleted=true", from.getUid()) + // .content(HttpStatus.OK) + // .getList("relationships", JsonRelationship.class); + // + // assertFirstRelationship(r, relationships); + // } + // + // @Test + // void shouldGetRelationshipsByEnrollmentWhenRelationshipIsDeleted() { + // TrackedEntity to = trackedEntity(); + // Enrollment from = enrollment(to); + // Relationship r = relationship(from, to); + // + // r.setDeleted(true); + // manager.update(r); + // switchContextToUser(user); + // + // JsonList relationships = + // GET("/tracker/relationships?enrollment={en}&includeDeleted=true", from.getUid()) + // .content(HttpStatus.OK) + // .getList("relationships", JsonRelationship.class); + // + // assertFirstRelationship(r, relationships); + // } + // + // @Test + // void getRelationshipsByDeprecatedTei() { + // TrackedEntity to = trackedEntity(); + // Enrollment from = enrollment(to); + // Relationship r = relationship(from, to); + // switchContextToUser(user); + // + // JsonList relationships = + // GET("/tracker/relationships?tei=" + to.getUid()) + // .content(HttpStatus.OK) + // .getList("relationships", JsonRelationship.class); + // + // JsonObject relationship = assertFirstRelationship(r, relationships); + // assertHasOnlyMembers(relationship, "relationship", "relationshipType", "from", "to"); + // assertHasOnlyUid(from.getUid(), "enrollment", relationship.getObject("from")); + // assertHasOnlyUid(to.getUid(), "trackedEntity", relationship.getObject("to")); + // } + // + // @Test + // void getRelationshipsByTrackedEntityWithEnrollments() { + // TrackedEntity to = trackedEntity(); + // Enrollment from = enrollment(to); + // relationship(from, to); + // switchContextToUser(user); + // + // JsonList relationships = + // GET( + // + // "/tracker/relationships?trackedEntity={trackedEntity}&fields=to[trackedEntity[enrollments[enrollment,trackedEntity]]", + // to.getUid()) + // .content(HttpStatus.OK) + // .getList("relationships", JsonRelationship.class); + // + // JsonRelationshipItem.JsonEnrollment enrollment = + // relationships.get(0).getTo().getTrackedEntity().getEnrollments().get(0); + // assertEquals(from.getUid(), enrollment.getEnrollment()); + // assertEquals(to.getUid(), enrollment.getTrackedEntity()); + // } + // + // @Test + // void getRelationshipsByTrackedEntityAndEnrollmentWithAttributesIsEmpty() { + // // Tracked entity attribute values are owned by the tracked entity and only mapped onto the + // // enrollment on export. Program tracked entity attributes are only returned by the + // underlying + // // TE service if a program is + // // provided which is not possible on the relationship endpoint. + // TrackedEntity to = trackedEntity(orgUnit); + // to.setTrackedEntityAttributeValues( + // Set.of(attributeValue(tea, to, "12"), attributeValue(tea2, to, "24"))); + // program.setProgramAttributes(List.of(createProgramTrackedEntityAttribute(program, tea2))); + // Enrollment from = enrollment(to); + // Relationship relationship = relationship(from, to); + // + // RelationshipType type = relationship.getRelationshipType(); + // + // RelationshipConstraint fromConstraint = new RelationshipConstraint(); + // + // TrackerDataView trackerDataView = new TrackerDataView(); + // trackerDataView.setAttributes(new LinkedHashSet<>(Set.of(tea2.getUid()))); + // + // fromConstraint.setTrackerDataView(trackerDataView); + // + // RelationshipConstraint toConstraint = new RelationshipConstraint(); + // + // TrackerDataView dataView = new TrackerDataView(); + // dataView.setAttributes(new LinkedHashSet<>(Set.of(tea.getUid(), tea2.getUid()))); + // + // toConstraint.setTrackerDataView(dataView); + // + // type.setFromConstraint(fromConstraint); + // type.setToConstraint(toConstraint); + // switchContextToUser(user); + // + // JsonList relationships = + // GET( + // + // "/tracker/relationships?trackedEntity={trackedEntity}&fields=from[enrollment[attributes[attribute,value]]],to[trackedEntity[attributes[attribute,value]]]", + // to.getUid()) + // .content(HttpStatus.OK) + // .getList("relationships", JsonRelationship.class); + // + // JsonList enrollmentAttr = + // relationships.get(0).getFrom().getEnrollment().getAttributes(); + // assertIsEmpty( + // enrollmentAttr.toList(JsonAttribute::getAttribute), + // "program attributes should not be returned as no program can be provided"); + // JsonList teAttributes = + // relationships.get(0).getTo().getTrackedEntity().getAttributes(); + // assertContainsAll(List.of(tea.getUid()), teAttributes, JsonAttribute::getAttribute); + // assertContainsAll(List.of("12"), teAttributes, JsonAttribute::getValue); + // } + // + // @Test + // void getRelationshipsByTrackedEntityWithProgramOwners() { + // TrackedEntity to = trackedEntity(orgUnit); + // Enrollment from = enrollment(to); + // to.setProgramOwners(Set.of(new TrackedEntityProgramOwner(to, from.getProgram(), orgUnit))); + // relationship(from, to); + // switchContextToUser(user); + // + // JsonList relationships = + // GET( + // + // "/tracker/relationships?trackedEntity={trackedEntity}&fields=to[trackedEntity[programOwners]", + // to.getUid()) + // .content(HttpStatus.OK) + // .getList("relationships", JsonRelationship.class); + // + // JsonProgramOwner jsonProgramOwner = + // relationships.get(0).getTo().getTrackedEntity().getProgramOwners().get(0); + // assertEquals(orgUnit.getUid(), jsonProgramOwner.getOrgUnit()); + // assertEquals(to.getUid(), jsonProgramOwner.getTrackedEntity()); + // assertEquals(from.getProgram().getUid(), jsonProgramOwner.getProgram()); + // } + // + // @Test + // void getRelationshipsByTrackedEntityRelationshipTeToTe() { + // TrackedEntity from = trackedEntity(); + // TrackedEntity to = trackedEntity(); + // Relationship r = relationship(from, to); + // switchContextToUser(user); + // + // JsonList relationships = + // GET("/tracker/relationships?trackedEntity={trackedEntity}", from.getUid()) + // .content(HttpStatus.OK) + // .getList("relationships", JsonRelationship.class); + // + // JsonObject relationship = assertFirstRelationship(r, relationships); + // assertHasOnlyMembers(relationship, "relationship", "relationshipType", "from", "to"); + // assertHasOnlyUid(from.getUid(), "trackedEntity", relationship.getObject("from")); + // assertHasOnlyUid(to.getUid(), "trackedEntity", relationship.getObject("to")); + // } + // + // @Test + // void shouldRetrieveRelationshipWhenUserHasAccessToRelationship() { + // TrackedEntity from = trackedEntity(); + // TrackedEntity to = trackedEntity(); + // Relationship r = relationship(from, to); + // switchContextToUser(user); + // + // JsonList relationships = + // GET("/tracker/relationships?trackedEntity={trackedEntity}", from.getUid()) + // .content(HttpStatus.OK) + // .getList("relationships", JsonRelationship.class); + // + // JsonObject relationship = assertFirstRelationship(r, relationships); + // assertHasOnlyMembers(relationship, "relationship", "relationshipType", "from", "to"); + // assertHasOnlyUid(from.getUid(), "trackedEntity", relationship.getObject("from")); + // assertHasOnlyUid(to.getUid(), "trackedEntity", relationship.getObject("to")); + // } + // + // @Test + // void getRelationshipsByTrackedEntityRelationshipsNoAccessToRelationshipType() { + // TrackedEntity from = trackedEntity(); + // TrackedEntity to = trackedEntity(); + // relationship(relationshipTypeNotAccessible(), from, to); + // switchContextToUser(user); + // + // assertNoRelationships( + // GET("/tracker/relationships?trackedEntity={trackedEntity}", from.getUid()) + // .content(HttpStatus.OK)); + // } + // + // @Test + // void shouldRetrieveNoRelationshipsWhenUserHasNoAccessToRelationshipItemTo() { + // TrackedEntity from = trackedEntity(); + // TrackedEntity to = trackedEntityNotInSearchScope(); + // relationship(from, to); + // switchContextToUser(user); + // + // assertNoRelationships( + // GET("/tracker/relationships?trackedEntity={trackedEntity}", from.getUid()) + // .content(HttpStatus.OK)); + // } + // + // @Test + // void shouldReturnForbiddenWhenUserHasNoAccessToRelationshipItemFrom() { + // TrackedEntity from = trackedEntityNotInSearchScope(); + // TrackedEntity to = trackedEntity(); + // relationship(from, to); + // switchContextToUser(user); + // + // assertEquals( + // HttpStatus.FORBIDDEN, + // GET("/tracker/relationships?trackedEntity={trackedEntity}", from.getUid()).status()); + // } + // + // @Test + // void + // + // shouldReturnForbiddenWhenGetRelationshipsByTrackedEntityWithNotAccessibleTrackedEntityType() { + // TrackedEntityType type = trackedEntityTypeNotAccessible(); + // TrackedEntity from = trackedEntity(type); + // TrackedEntity to = trackedEntity(type); + // relationship(from, to); + // switchContextToUser(user); + // + // assertEquals( + // HttpStatus.FORBIDDEN, + // GET("/tracker/relationships?trackedEntity={trackedEntity}", from.getUid()).status()); + // } + // + // @Test + // void getRelationshipsByTrackedEntityNotFound() { + // assertStartsWith( + // "TrackedEntity with id Hq3Kc6HK4OZ", + // GET("/tracker/relationships?trackedEntity=Hq3Kc6HK4OZ") + // .error(HttpStatus.NOT_FOUND) + // .getMessage()); + // } + + private T get(Class type, String uid) { + T t = manager.get(type, uid); + assertNotNull( + t, + () -> + String.format( + "'%s' with uid '%s' should have been created", type.getSimpleName(), uid)); + return t; + } + + public static void assertNoErrors(ImportReport report) { + assertNotNull(report); assertEquals( - HttpStatus.FORBIDDEN, - GET("/tracker/relationships?trackedEntity={trackedEntity}", from.getUid()).status()); - } - - @Test - void getRelationshipsByTrackedEntityNotFound() { - assertStartsWith( - "TrackedEntity with id Hq3Kc6HK4OZ", - GET("/tracker/relationships?trackedEntity=Hq3Kc6HK4OZ") - .error(HttpStatus.NOT_FOUND) - .getMessage()); - } - - private TrackedEntityType trackedEntityTypeAccessible() { - TrackedEntityType type = trackedEntityType('A'); - type.getSharing().addUserAccess(userAccess()); - manager.save(type, false); - return type; - } - - private TrackedEntityType trackedEntityTypeNotAccessible() { - TrackedEntityType type = trackedEntityType('B'); - manager.save(type, false); - return type; - } - - private TrackedEntityType trackedEntityType(char uniqueChar) { - TrackedEntityType type = createTrackedEntityType(uniqueChar); - type.getSharing().setOwner(owner); - type.getSharing().setPublicAccess(AccessStringHelper.DEFAULT); - return type; - } - - private TrackedEntity trackedEntity() { - TrackedEntity te = trackedEntity(orgUnit); - manager.save(te, false); - return te; - } - - private TrackedEntity trackedEntityNotInSearchScope() { - TrackedEntity te = trackedEntity(anotherOrgUnit); - manager.save(te, false); - return te; - } - - private TrackedEntity trackedEntity(TrackedEntityType trackedEntityType) { - TrackedEntity te = trackedEntity(orgUnit, trackedEntityType); - manager.save(te, false); - return te; - } - - private TrackedEntity trackedEntity(OrganisationUnit orgUnit) { - TrackedEntity te = trackedEntity(orgUnit, trackedEntityType); - manager.save(te, false); - return te; - } - - private TrackedEntity trackedEntity( - OrganisationUnit orgUnit, TrackedEntityType trackedEntityType) { - TrackedEntity te = createTrackedEntity(orgUnit, trackedEntityType); - te.getSharing().setPublicAccess(AccessStringHelper.DEFAULT); - te.getSharing().setOwner(owner); - return te; - } - - private Enrollment enrollment(TrackedEntity te) { - Enrollment enrollment = new Enrollment(program, te, orgUnit); - enrollment.setAutoFields(); - enrollment.setEnrollmentDate(new Date()); - enrollment.setOccurredDate(new Date()); - enrollment.setStatus(EnrollmentStatus.COMPLETED); - manager.save(enrollment, false); - te.setEnrollments(Set.of(enrollment)); - manager.save(te, false); - return enrollment; - } - - private Event event(Enrollment enrollment) { - Event event = new Event(enrollment, programStage, orgUnit, coc); - event.setAutoFields(); - manager.save(event, false); - enrollment.setEvents(Set.of(event)); - manager.save(enrollment, false); - return event; - } - - private UserAccess userAccess() { - UserAccess a = new UserAccess(); - a.setUser(user); - a.setAccess(AccessStringHelper.FULL); - return a; - } - - private RelationshipType relationshipTypeAccessible( - RelationshipEntity from, RelationshipEntity to) { - RelationshipType type = relationshipType(from, to); - type.getSharing().addUserAccess(userAccess()); - manager.save(type, false); - return type; - } - - private RelationshipType relationshipTypeNotAccessible() { - return relationshipType( - RelationshipEntity.TRACKED_ENTITY_INSTANCE, RelationshipEntity.TRACKED_ENTITY_INSTANCE); - } - - private RelationshipType relationshipType(RelationshipEntity from, RelationshipEntity to) { - RelationshipType type = createRelationshipType('A'); - type.getFromConstraint().setRelationshipEntity(from); - type.getToConstraint().setRelationshipEntity(to); - type.getSharing().setOwner(owner); - type.getSharing().setPublicAccess(AccessStringHelper.DEFAULT); - manager.save(type, false); - return type; - } - - private Relationship relationship(TrackedEntity from, TrackedEntity to) { - - RelationshipType type = - relationshipTypeAccessible( - RelationshipEntity.TRACKED_ENTITY_INSTANCE, RelationshipEntity.TRACKED_ENTITY_INSTANCE); - return relationship(type, from, to); - } - - private Relationship relationship(RelationshipType type, TrackedEntity from, TrackedEntity to) { - Relationship r = new Relationship(); - - RelationshipItem fromItem = new RelationshipItem(); - fromItem.setTrackedEntity(from); - from.getRelationshipItems().add(fromItem); - r.setFrom(fromItem); - fromItem.setRelationship(r); - - RelationshipItem toItem = new RelationshipItem(); - toItem.setTrackedEntity(to); - to.getRelationshipItems().add(toItem); - r.setTo(toItem); - toItem.setRelationship(r); - - r.setRelationshipType(type); - r.setKey(type.getUid()); - r.setInvertedKey(type.getUid()); - r.setAutoFields(); - r.getSharing().setOwner(owner); - manager.save(r, false); - return r; - } - - private Relationship relationship(Event from, TrackedEntity to) { - Relationship r = new Relationship(); - - RelationshipItem fromItem = new RelationshipItem(); - fromItem.setEvent(from); - from.getRelationshipItems().add(fromItem); - r.setFrom(fromItem); - fromItem.setRelationship(r); - - RelationshipItem toItem = new RelationshipItem(); - toItem.setTrackedEntity(to); - to.getRelationshipItems().add(toItem); - r.setTo(toItem); - toItem.setRelationship(r); - - RelationshipType type = - relationshipTypeAccessible( - RelationshipEntity.PROGRAM_STAGE_INSTANCE, RelationshipEntity.TRACKED_ENTITY_INSTANCE); - r.setRelationshipType(type); - r.setKey(type.getUid()); - r.setInvertedKey(type.getUid()); - - r.setAutoFields(); - r.getSharing().setOwner(owner); - r.setCreatedAtClient(new Date()); - manager.save(r, false); - return r; - } - - private void relationship(Enrollment from, Event to) { - Relationship r = new Relationship(); - - RelationshipItem fromItem = new RelationshipItem(); - fromItem.setEnrollment(from); - from.getRelationshipItems().add(fromItem); - r.setFrom(fromItem); - fromItem.setRelationship(r); - - RelationshipItem toItem = new RelationshipItem(); - toItem.setEvent(to); - to.getRelationshipItems().add(toItem); - r.setTo(toItem); - toItem.setRelationship(r); - - RelationshipType type = - relationshipTypeAccessible( - RelationshipEntity.PROGRAM_INSTANCE, RelationshipEntity.PROGRAM_STAGE_INSTANCE); - r.setRelationshipType(type); - r.setKey(type.getUid()); - r.setInvertedKey(type.getUid()); - - r.setAutoFields(); - r.getSharing().setOwner(owner); - manager.save(r, false); - } - - private Relationship relationship(Enrollment from, TrackedEntity to) { - manager.save(from, false); - manager.save(to, false); - - Relationship r = new Relationship(); - - RelationshipItem fromItem = new RelationshipItem(); - fromItem.setEnrollment(from); - from.getRelationshipItems().add(fromItem); - r.setFrom(fromItem); - fromItem.setRelationship(r); - - RelationshipItem toItem = new RelationshipItem(); - toItem.setTrackedEntity(to); - to.getRelationshipItems().add(toItem); - r.setTo(toItem); - toItem.setRelationship(r); - - RelationshipType type = - relationshipTypeAccessible( - RelationshipEntity.PROGRAM_INSTANCE, RelationshipEntity.TRACKED_ENTITY_INSTANCE); - r.setRelationshipType(type); - r.setKey(type.getUid()); - r.setInvertedKey(type.getUid()); - - r.setAutoFields(); - r.getSharing().setOwner(owner); - manager.save(r, false); - return r; - } - - private TrackedEntityAttributeValue attributeValue( - TrackedEntityAttribute tea, TrackedEntity te, String value) { - return new TrackedEntityAttributeValue(tea, te, value); - } - - private Note note(String uid, String value, String storedBy) { - Note note = new Note(value, storedBy); - note.setUid(uid); - manager.save(note, false); - return note; + Status.OK, + report.getStatus(), + errorMessage( + "Expected import with status OK, instead got:%n", report.getValidationReport())); + } + + private static Supplier errorMessage(String errorTitle, ValidationReport report) { + return () -> { + StringBuilder msg = new StringBuilder(errorTitle); + report + .getErrors() + .forEach( + e -> { + msg.append(e.getErrorCode()); + msg.append(": "); + msg.append(e.getMessage()); + msg.append('\n'); + }); + return msg.toString(); + }; + } + + public static void assertNoErrors(ObjectBundleValidationReport report) { + assertNotNull(report); + List errors = new ArrayList<>(); + report.forEachErrorReport(err -> errors.add(err.toString())); + assertFalse( + report.hasErrorReports(), String.format("Expected no errors, instead got: %s%n", errors)); } } diff --git a/dhis-2/dhis-test-web-api/src/test/resources/tracker/event_and_enrollment.json b/dhis-2/dhis-test-web-api/src/test/resources/tracker/event_and_enrollment.json index d4c339310e31..99d6ec612a5a 100644 --- a/dhis-2/dhis-test-web-api/src/test/resources/tracker/event_and_enrollment.json +++ b/dhis-2/dhis-test-web-api/src/test/resources/tracker/event_and_enrollment.json @@ -1180,7 +1180,7 @@ "trackedEntity": "guVNoAerxWo" }, "to": { - "enrollment": "nxP7UnKhomJ" + "enrollment": "ipBifypAQTo" } } ], From d5962adf0f1efd603a41246c6c0af9fdb5aef9a4 Mon Sep 17 00:00:00 2001 From: Enrico Date: Fri, 31 Jan 2025 15:29:55 +0100 Subject: [PATCH 2/2] Enhance unit tests --- ...RelationshipOperationParamsMapperTest.java | 64 ++++++++++++++++++- 1 file changed, 63 insertions(+), 1 deletion(-) diff --git a/dhis-2/dhis-services/dhis-service-tracker/src/test/java/org/hisp/dhis/tracker/export/relationship/RelationshipOperationParamsMapperTest.java b/dhis-2/dhis-services/dhis-service-tracker/src/test/java/org/hisp/dhis/tracker/export/relationship/RelationshipOperationParamsMapperTest.java index 2341d54c16bd..58729472fa97 100644 --- a/dhis-2/dhis-services/dhis-service-tracker/src/test/java/org/hisp/dhis/tracker/export/relationship/RelationshipOperationParamsMapperTest.java +++ b/dhis-2/dhis-services/dhis-service-tracker/src/test/java/org/hisp/dhis/tracker/export/relationship/RelationshipOperationParamsMapperTest.java @@ -33,6 +33,7 @@ import static org.hisp.dhis.tracker.TrackerType.TRACKED_ENTITY; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.when; import java.util.List; @@ -51,6 +52,7 @@ import org.hisp.dhis.tracker.acl.TrackerAccessManager; import org.hisp.dhis.tracker.export.Order; import org.hisp.dhis.user.SystemUser; +import org.hisp.dhis.user.UserDetails; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -79,6 +81,8 @@ class RelationshipOperationParamsMapperTest extends TestBase { private Event event; + private UserDetails user; + @BeforeEach public void setUp() { OrganisationUnit organisationUnit = createOrganisationUnit('A'); @@ -91,7 +95,8 @@ public void setUp() { enrollment.setUid(EN_UID.getValue()); event = createEvent(programStage, enrollment, organisationUnit); event.setUid(EV_UID.getValue()); - injectSecurityContextNoSettings(new SystemUser()); + user = new SystemUser(); + injectSecurityContextNoSettings(user); } @Test @@ -107,6 +112,25 @@ void shouldMapTrackedEntityWhenATrackedEntityIsPassed() assertEquals(TE_UID.getValue(), queryParams.getEntity().getUid()); } + @Test + void shouldThrowNotFoundExceptionWhenATrackedEntityIsNotPresent() { + when(relationshipStore.findTrackedEntity(TE_UID)).thenReturn(Optional.empty()); + RelationshipOperationParams params = + RelationshipOperationParams.builder().type(TRACKED_ENTITY).identifier(TE_UID).build(); + + assertThrows(NotFoundException.class, () -> mapper.map(params)); + } + + @Test + void shouldThrowForbiddenExceptionWhenATrackedEntityIsNotAccessible() { + when(relationshipStore.findTrackedEntity(TE_UID)).thenReturn(Optional.of(trackedEntity)); + when(trackerAccessManager.canRead(user, trackedEntity)).thenReturn(List.of("error")); + RelationshipOperationParams params = + RelationshipOperationParams.builder().type(TRACKED_ENTITY).identifier(TE_UID).build(); + + assertThrows(ForbiddenException.class, () -> mapper.map(params)); + } + @Test void shouldMapEnrollmentWhenAEnrollmentIsPassed() throws NotFoundException, ForbiddenException { when(relationshipStore.findEnrollment(EN_UID)).thenReturn(Optional.of(enrollment)); @@ -119,6 +143,25 @@ void shouldMapEnrollmentWhenAEnrollmentIsPassed() throws NotFoundException, Forb assertEquals(EN_UID.getValue(), queryParams.getEntity().getUid()); } + @Test + void shouldThrowNotFoundExceptionWhenAnEnrollmentIsNotPresent() { + when(relationshipStore.findEnrollment(EN_UID)).thenReturn(Optional.empty()); + RelationshipOperationParams params = + RelationshipOperationParams.builder().type(ENROLLMENT).identifier(EN_UID).build(); + + assertThrows(NotFoundException.class, () -> mapper.map(params)); + } + + @Test + void shouldThrowForbiddenExceptionWhenAnEnrollmentIsNotAccessible() { + when(relationshipStore.findEnrollment(EN_UID)).thenReturn(Optional.of(enrollment)); + when(trackerAccessManager.canRead(user, enrollment, false)).thenReturn(List.of("error")); + RelationshipOperationParams params = + RelationshipOperationParams.builder().type(ENROLLMENT).identifier(EN_UID).build(); + + assertThrows(ForbiddenException.class, () -> mapper.map(params)); + } + @Test void shouldMapEventWhenAEventIsPassed() throws NotFoundException, ForbiddenException { when(relationshipStore.findEvent(EV_UID)).thenReturn(Optional.of(event)); @@ -131,6 +174,25 @@ void shouldMapEventWhenAEventIsPassed() throws NotFoundException, ForbiddenExcep assertEquals(EV_UID.getValue(), queryParams.getEntity().getUid()); } + @Test + void shouldThrowNotFoundExceptionWhenAnEventIsNotPresent() { + when(relationshipStore.findEvent(EV_UID)).thenReturn(Optional.empty()); + RelationshipOperationParams params = + RelationshipOperationParams.builder().type(EVENT).identifier(EV_UID).build(); + + assertThrows(NotFoundException.class, () -> mapper.map(params)); + } + + @Test + void shouldThrowForbiddenExceptionWhenAnEventIsNotAccessible() { + when(relationshipStore.findEvent(EV_UID)).thenReturn(Optional.of(event)); + when(trackerAccessManager.canRead(user, event, false)).thenReturn(List.of("error")); + RelationshipOperationParams params = + RelationshipOperationParams.builder().type(EVENT).identifier(EV_UID).build(); + + assertThrows(ForbiddenException.class, () -> mapper.map(params)); + } + @Test void shouldMapOrderInGivenOrder() throws ForbiddenException, NotFoundException { when(relationshipStore.findTrackedEntity(TE_UID)).thenReturn(Optional.of(trackedEntity));