package ca.uhn.fhir.jpa.dao.dstu3; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.empty; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import java.util.HashSet; import java.util.Set; import org.hl7.fhir.dstu3.model.Organization; import org.hl7.fhir.dstu3.model.Patient; import org.hl7.fhir.instance.model.api.IIdType; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.Test; import ca.uhn.fhir.jpa.dao.DaoConfig; import ca.uhn.fhir.jpa.dao.SearchParameterMap; import ca.uhn.fhir.rest.param.ReferenceParam; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.util.TestUtil; public class FhirResourceDaoDstu3ExternalReferenceTest extends BaseJpaDstu3Test { @Before public void beforeDisableResultReuse() { myDaoConfig.setReuseCachedSearchResultsForMillis(null); } @AfterClass public static void afterClassClearContext() { TestUtil.clearAllStaticFieldsForUnitTest(); } @Before @After public void resetDefaultBehaviour() { // Reset to default myDaoConfig.setAllowExternalReferences(new DaoConfig().isAllowExternalReferences()); myDaoConfig.setTreatBaseUrlsAsLocal(null); } @Test public void testInternalReferenceBlockedByDefault() { Patient p = new Patient(); p.getManagingOrganization().setReference("Organization/FOO"); try { myPatientDao.create(p, mySrd); fail(); } catch (InvalidRequestException e) { assertEquals("Resource Organization/FOO not found, specified in path: Patient.managingOrganization", e.getMessage()); } } @Test public void testExternalReferenceBlockedByDefault() { Organization org = new Organization(); org.setId("FOO"); org.setName("Org Name"); myOrganizationDao.update(org, mySrd); Patient p = new Patient(); p.getManagingOrganization().setReference("http://example.com/base/Organization/FOO"); try { myPatientDao.create(p, mySrd); fail(); } catch (InvalidRequestException e) { assertEquals("Resource contains external reference to URL \"http://example.com/base/Organization/FOO\" but this server is not configured to allow external references", e.getMessage()); } } @Test public void testExternalReferenceAllowed() { Organization org = new Organization(); org.setId("FOO"); org.setName("Org Name"); myOrganizationDao.update(org, mySrd); myDaoConfig.setAllowExternalReferences(true); Patient p = new Patient(); p.getManagingOrganization().setReference("http://example.com/base/Organization/FOO"); IIdType pid = myPatientDao.create(p, mySrd).getId().toUnqualifiedVersionless(); SearchParameterMap map = new SearchParameterMap(); map.add(Patient.SP_ORGANIZATION, new ReferenceParam("http://example.com/base/Organization/FOO")); assertThat(toUnqualifiedVersionlessIdValues(myPatientDao.search(map)), contains(pid.getValue())); map = new SearchParameterMap(); map.add(Patient.SP_ORGANIZATION, new ReferenceParam("http://example2.com/base/Organization/FOO")); assertThat(toUnqualifiedVersionlessIdValues(myPatientDao.search(map)), empty()); } @Test public void testExternalReferenceReplaced() { Organization org = new Organization(); org.setId("FOO"); org.setName("Org Name"); org.getPartOf().setDisplay("Parent"); // <-- no reference, make sure this works myOrganizationDao.update(org, mySrd); Set<String> urls = new HashSet<String>(); urls.add("http://example.com/base/"); myDaoConfig.setTreatBaseUrlsAsLocal(urls); Patient p = new Patient(); p.getManagingOrganization().setReference("http://example.com/base/Organization/FOO"); IIdType pid = myPatientDao.create(p, mySrd).getId().toUnqualifiedVersionless(); p = myPatientDao.read(pid, mySrd); assertEquals("Organization/FOO", p.getManagingOrganization().getReference()); SearchParameterMap map; map = new SearchParameterMap(); map.add(Patient.SP_ORGANIZATION, new ReferenceParam("http://example.com/base/Organization/FOO")); assertThat(toUnqualifiedVersionlessIdValues(myPatientDao.search(map)), contains(pid.getValue())); } @Test public void testSearchForInvalidLocalReference() { SearchParameterMap map; map = new SearchParameterMap(); map.add(Patient.SP_ORGANIZATION, new ReferenceParam("Organization/FOO")); assertThat(toUnqualifiedVersionlessIdValues(myPatientDao.search(map)), empty()); map = new SearchParameterMap(); map.add(Patient.SP_ORGANIZATION, new ReferenceParam("Organization/9999999999")); assertThat(toUnqualifiedVersionlessIdValues(myPatientDao.search(map)), empty()); } @Test public void testExternalReferenceReplacedWrongDoesntMatch() { Organization org = new Organization(); org.setId("FOO"); org.setName("Org Name"); org.getPartOf().setDisplay("Parent"); // <-- no reference, make sure this works myOrganizationDao.update(org, mySrd); Set<String> urls = new HashSet<String>(); urls.add("http://example.com/base/"); myDaoConfig.setTreatBaseUrlsAsLocal(urls); Patient p = new Patient(); p.getManagingOrganization().setReference("http://example.com/base/Organization/FOO"); IIdType pid = myPatientDao.create(p, mySrd).getId().toUnqualifiedVersionless(); p = myPatientDao.read(pid, mySrd); assertEquals("Organization/FOO", p.getManagingOrganization().getReference()); SearchParameterMap map; // Different base map = new SearchParameterMap(); map.add(Patient.SP_ORGANIZATION, new ReferenceParam("http://foo.com/base/Organization/FOO")); assertThat(toUnqualifiedVersionlessIdValues(myPatientDao.search(map)), empty()); } }