From 479e412786f1d49c3336c77579338bef43532551 Mon Sep 17 00:00:00 2001 From: Luke deGruchy Date: Tue, 28 Mar 2023 10:41:24 -0400 Subject: [PATCH] Ensure that source resource type of Provenance is also excluded from the $everything linkage. (#4692) --- ...-linked-by-provenance-and-composition.yaml | 5 ++ .../jpa/search/builder/SearchBuilder.java | 1 + .../provider/r4/ResourceProviderR4Test.java | 50 +++++++++++++++++++ .../ca/uhn/fhir/jpa/test/BaseJpaR4Test.java | 4 ++ 4 files changed, 60 insertions(+) create mode 100644 hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_6_0/4691-everything-two-patients-linked-by-provenance-and-composition.yaml diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_6_0/4691-everything-two-patients-linked-by-provenance-and-composition.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_6_0/4691-everything-two-patients-linked-by-provenance-and-composition.yaml new file mode 100644 index 00000000000..8b3c36678fa --- /dev/null +++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_6_0/4691-everything-two-patients-linked-by-provenance-and-composition.yaml @@ -0,0 +1,5 @@ +--- +type: change +issue: 4691 +title: "When calling $everything on a Patient instance, the jpa server no longer traverses into other patients. +Previously it was possible to pull in data from another patient for example, via Provenance and Composition resources." diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/builder/SearchBuilder.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/builder/SearchBuilder.java index 867b828ee15..f5a898c8693 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/builder/SearchBuilder.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/builder/SearchBuilder.java @@ -1176,6 +1176,7 @@ public class SearchBuilder implements ISearchBuilder { // (e.g. via Provenance, List, or Group) when in an $everything operation if (myParams != null && myParams.getEverythingMode() == SearchParameterMap.EverythingModeEnum.PATIENT_INSTANCE) { sqlBuilder.append(" AND r.myTargetResourceType != 'Patient'"); + sqlBuilder.append(" AND r.mySourceResourceType != 'Provenance'"); } String sql = sqlBuilder.toString(); diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4Test.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4Test.java index ea04a400259..4e62135724c 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4Test.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4Test.java @@ -99,6 +99,7 @@ import org.hl7.fhir.r4.model.CodeSystem; import org.hl7.fhir.r4.model.CodeType; import org.hl7.fhir.r4.model.CodeableConcept; import org.hl7.fhir.r4.model.Coding; +import org.hl7.fhir.r4.model.Composition; import org.hl7.fhir.r4.model.ConceptMap; import org.hl7.fhir.r4.model.Condition; import org.hl7.fhir.r4.model.Coverage; @@ -3799,6 +3800,55 @@ public class ResourceProviderR4Test extends BaseResourceProviderR4Test { assertThat(ids, containsInAnyOrder(goodPid, oid, provid)); } + @Test + public void testEverythingDoesNotEnterSecondPatientLinkedByProvenanceAndComposition() { + final Patient desiredPatient = new Patient(); + desiredPatient.setActive(true); + final String desiredPid = myPatientDao.create(desiredPatient, mySrd).getId().toUnqualifiedVersionless().getValue(); + + final Patient notDesiredPatient = new Patient(); + desiredPatient.setActive(true); + final String notDesiredPid = myPatientDao.create(notDesiredPatient, mySrd).getId().toUnqualifiedVersionless().getValue(); + + final Observation desiredObservation = new Observation(); + desiredObservation.getSubject().setReference(desiredPid); + desiredObservation.addIdentifier().setSystem("foo").setValue("1"); + final String desiredObservationId = myObservationDao.create(desiredObservation, mySrd).getId().toUnqualifiedVersionless().getValue(); + + final Observation notDesiredObservation = new Observation(); + notDesiredObservation.getSubject().setReference(notDesiredPid); + notDesiredObservation.addIdentifier().setSystem("foo").setValue("1"); + final String notDesiredObservationId = myObservationDao.create(notDesiredObservation, mySrd).getId().toUnqualifiedVersionless().getValue(); + + final Composition composition = new Composition(); + final Reference referenceToNotDesiredPatient = new Reference(); + referenceToNotDesiredPatient.setReference(notDesiredPid); + composition.setSubject(referenceToNotDesiredPatient); + final String compositionId = myCompositionDao.create(composition, mySrd).getId().toUnqualifiedVersionless().getValue(); + + final Provenance desiredProvenance = new Provenance(); + desiredProvenance.addTarget().setReference(desiredPid); + desiredProvenance.addTarget().setReference(compositionId); + final String desiredProvenanceId = myProvenanceDao.create(desiredProvenance, mySrd).getId().toUnqualifiedVersionless().getValue(); + + final Provenance notDesiredProvenance = new Provenance(); + notDesiredProvenance.addTarget().setReference(notDesiredPid); + notDesiredProvenance.addTarget().setReference(compositionId); + final String notDesiredProvenanceId = myProvenanceDao.create(notDesiredProvenance, mySrd).getId().toUnqualifiedVersionless().getValue(); + + final Bundle response = myClient + .operation() + .onInstance(new IdType(desiredPid)) + .named("everything") + .withNoParameters(Parameters.class) + .returnResourceType(Bundle.class) + .execute(); + + final List actualResourceIds = toUnqualifiedVersionlessIdValues(response); + // We should not pick up other resources via the notDesiredProvenance + assertThat(actualResourceIds, containsInAnyOrder(desiredPid, desiredObservationId, desiredProvenanceId)); + } + @Test public void testIncludeRecurseFromProvenanceDoesTraverse() { Patient goodPatient = new Patient(); diff --git a/hapi-fhir-jpaserver-test-utilities/src/main/java/ca/uhn/fhir/jpa/test/BaseJpaR4Test.java b/hapi-fhir-jpaserver-test-utilities/src/main/java/ca/uhn/fhir/jpa/test/BaseJpaR4Test.java index b8036f16bd8..0a32d6177a0 100644 --- a/hapi-fhir-jpaserver-test-utilities/src/main/java/ca/uhn/fhir/jpa/test/BaseJpaR4Test.java +++ b/hapi-fhir-jpaserver-test-utilities/src/main/java/ca/uhn/fhir/jpa/test/BaseJpaR4Test.java @@ -125,6 +125,7 @@ import org.hl7.fhir.r4.model.CodeSystem; import org.hl7.fhir.r4.model.Communication; import org.hl7.fhir.r4.model.CommunicationRequest; import org.hl7.fhir.r4.model.CompartmentDefinition; +import org.hl7.fhir.r4.model.Composition; import org.hl7.fhir.r4.model.ConceptMap; import org.hl7.fhir.r4.model.ConceptMap.ConceptMapGroupComponent; import org.hl7.fhir.r4.model.ConceptMap.SourceElementComponent; @@ -380,6 +381,9 @@ public abstract class BaseJpaR4Test extends BaseJpaTest implements ITestDataBuil @Qualifier("myObservationDaoR4") protected IFhirResourceDao myObservationDao; @Autowired + @Qualifier("myCompositionDaoR4") + protected IFhirResourceDao myCompositionDao; + @Autowired @Qualifier("myOperationDefinitionDaoR4") protected IFhirResourceDao myOperationDefinitionDao; @Autowired