From 2e6b3d16d67e7e8e0898dab59b5dddc1a0f407b8 Mon Sep 17 00:00:00 2001 From: MykolaMedynskyiSCDR <110495727+MykolaMedynskyiSCDR@users.noreply.github.com> Date: Thu, 13 Oct 2022 11:05:04 -0400 Subject: [PATCH] 4017 creating a searchparameter with an expression referencing metasecurity will return error hapi 1118 (#4037) * Adding initial test reproducing the issue. * some comments and small refactoring to run pipeline to see the extent of the damage that this can cause. * Parsing dstu3 expression with FHIRpath parser * fixed code. * omitting searchParameter expression(xpath) validation for DSTU2 * Added test for search parameter with many expressions * changed deprecated method. * removed and modified custom search parameters tests for DSTU3 and DSTU2. * fixed code * Added change log * Test testIndexFailsIfInvalidSearchParameterExists() is back. * Update createResourceSearchParameter_withExpressionMetaSecurity_succeeds() test * Update createResourceSearchParameter_withExpressionMetaSecurity_succeeds() test * Refactoring if statement and exception message. * Refactoring tests and rewording changelog. * Fixing tests. * Fixing more tests. * Addressing comments from first code review. * Fixing issue number. Co-authored-by: peartree --- ...asecurity-will-return-error-hapi-1118.yaml | 5 + .../r4/FhirResourceDaoSearchParameterR4.java | 102 +++++++++--------- ...ceDaoDstu2SearchCustomSearchParamTest.java | 34 ------ ...ceDaoDstu3SearchCustomSearchParamTest.java | 37 +------ .../dstu3/ResourceProviderDstu3Test.java | 65 +++++++++-- ...ourceDaoR4SearchCustomSearchParamTest.java | 2 +- .../FhirResourceDaoSearchParameterR4Test.java | 2 +- ...sourceProviderCustomSearchParamR4Test.java | 2 +- .../provider/r4/ResourceProviderR4Test.java | 39 +++++++ 9 files changed, 158 insertions(+), 130 deletions(-) create mode 100644 hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/4017-creating-a-searchparameter-with-an-expression-referencing-metasecurity-will-return-error-hapi-1118.yaml diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/4017-creating-a-searchparameter-with-an-expression-referencing-metasecurity-will-return-error-hapi-1118.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/4017-creating-a-searchparameter-with-an-expression-referencing-metasecurity-will-return-error-hapi-1118.yaml new file mode 100644 index 00000000000..f63a3b2d05e --- /dev/null +++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/4017-creating-a-searchparameter-with-an-expression-referencing-metasecurity-will-return-error-hapi-1118.yaml @@ -0,0 +1,5 @@ +--- +type: fix +issue: 4017 +jira: SMILE-5046 +title: "Previously, creating a DSTU3 SearchParameter with an expression that does not start with a resource type would throw an error. This has been corrected." diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoSearchParameterR4.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoSearchParameterR4.java index 930664cc170..35755a31717 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoSearchParameterR4.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoSearchParameterR4.java @@ -1,22 +1,19 @@ package ca.uhn.fhir.jpa.dao.r4; -import ca.uhn.fhir.i18n.Msg; import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirVersionEnum; import ca.uhn.fhir.context.RuntimeSearchParam; +import ca.uhn.fhir.i18n.Msg; import ca.uhn.fhir.jpa.api.config.DaoConfig; import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoSearchParameter; import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao; import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.searchparam.extractor.ISearchParamExtractor; import ca.uhn.fhir.rest.api.server.RequestDetails; -import ca.uhn.fhir.rest.server.util.ISearchParamRegistry; -import ca.uhn.fhir.parser.DataFormatException; import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException; +import ca.uhn.fhir.rest.server.util.ISearchParamRegistry; import ca.uhn.fhir.util.ElementUtil; import ca.uhn.fhir.util.HapiExtensions; -import org.hl7.fhir.instance.model.api.IBase; -import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IPrimitiveType; import org.hl7.fhir.r4.model.CodeType; import org.hl7.fhir.r4.model.Enumerations; @@ -123,7 +120,7 @@ public class FhirResourceDaoSearchParameterR4 extends BaseHapiFhirResourceDao "true".equals(t.getValueAsPrimitive().getValueAsString())); + boolean isUnique = hasAnyExtensionUniqueSetTo(theResource, true); if (theResource.getType() != null && theResource.getType().name().equals(Enumerations.SearchParamType.COMPOSITE.name()) && isBlank(theResource.getExpression())) { @@ -135,8 +132,6 @@ public class FhirResourceDaoSearchParameterR4 extends BaseHapiFhirResourceDao theValueAsString.equals(t.getValueAsPrimitive().getValueAsString())); + } + } diff --git a/hapi-fhir-jpaserver-test-dstu2/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirResourceDaoDstu2SearchCustomSearchParamTest.java b/hapi-fhir-jpaserver-test-dstu2/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirResourceDaoDstu2SearchCustomSearchParamTest.java index 0b352fd5290..229c1e6b545 100644 --- a/hapi-fhir-jpaserver-test-dstu2/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirResourceDaoDstu2SearchCustomSearchParamTest.java +++ b/hapi-fhir-jpaserver-test-dstu2/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirResourceDaoDstu2SearchCustomSearchParamTest.java @@ -111,23 +111,6 @@ public class FhirResourceDaoDstu2SearchCustomSearchParamTest extends BaseJpaDstu } - @Test - public void testCreateInvalidParamInvalidResourceName() { - SearchParameter fooSp = new SearchParameter(); - fooSp.setBase(ResourceTypeEnum.PATIENT); - fooSp.setCode("foo"); - fooSp.setType(SearchParamTypeEnum.TOKEN); - fooSp.setXpath("PatientFoo.gender"); - fooSp.setXpathUsage(XPathUsageTypeEnum.NORMAL); - fooSp.setStatus(ConformanceResourceStatusEnum.ACTIVE); - try { - mySearchParameterDao.create(fooSp, mySrd); - fail(); - } catch (UnprocessableEntityException e) { - assertEquals(Msg.code(1118) + "Invalid SearchParameter.expression value \"PatientFoo.gender\": " + Msg.code(1684) + "Unknown resource name \"PatientFoo\" (this name is not known in FHIR version \"DSTU2\")", e.getMessage()); - } - } - @Test public void testCreateInvalidParamNoPath() { SearchParameter fooSp = new SearchParameter(); @@ -144,23 +127,6 @@ public class FhirResourceDaoDstu2SearchCustomSearchParamTest extends BaseJpaDstu } } - @Test - public void testCreateInvalidParamNoResourceName() { - SearchParameter fooSp = new SearchParameter(); - fooSp.setBase(ResourceTypeEnum.PATIENT); - fooSp.setCode("foo"); - fooSp.setType(SearchParamTypeEnum.TOKEN); - fooSp.setXpath("gender"); - fooSp.setXpathUsage(XPathUsageTypeEnum.NORMAL); - fooSp.setStatus(ConformanceResourceStatusEnum.ACTIVE); - try { - mySearchParameterDao.create(fooSp, mySrd); - fail(); - } catch (UnprocessableEntityException e) { - assertEquals(Msg.code(1117) + "Invalid SearchParameter.expression value \"gender\". Must start with a resource name.", e.getMessage()); - } - } - @Test public void testCreateInvalidParamParamNullStatus() { diff --git a/hapi-fhir-jpaserver-test-dstu3/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3SearchCustomSearchParamTest.java b/hapi-fhir-jpaserver-test-dstu3/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3SearchCustomSearchParamTest.java index ea2236d2224..46df7dd8150 100644 --- a/hapi-fhir-jpaserver-test-dstu3/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3SearchCustomSearchParamTest.java +++ b/hapi-fhir-jpaserver-test-dstu3/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3SearchCustomSearchParamTest.java @@ -120,23 +120,6 @@ public class FhirResourceDaoDstu3SearchCustomSearchParamTest extends BaseJpaDstu assertThat(daoMethodOutcome.getId(), is(notNullValue())); } - @Test - public void testCreateInvalidParamInvalidResourceName() { - SearchParameter fooSp = new SearchParameter(); - fooSp.addBase("Patient"); - fooSp.setCode("foo"); - fooSp.setType(org.hl7.fhir.dstu3.model.Enumerations.SearchParamType.TOKEN); - fooSp.setTitle("FOO SP"); - fooSp.setExpression("PatientFoo.gender"); - fooSp.setXpathUsage(org.hl7.fhir.dstu3.model.SearchParameter.XPathUsageType.NORMAL); - fooSp.setStatus(org.hl7.fhir.dstu3.model.Enumerations.PublicationStatus.ACTIVE); - try { - mySearchParameterDao.create(fooSp, mySrd); - fail(); - } catch (UnprocessableEntityException e) { - assertEquals(Msg.code(1118) + "Invalid SearchParameter.expression value \"PatientFoo.gender\": " + Msg.code(1684) + "Unknown resource name \"PatientFoo\" (this name is not known in FHIR version \"DSTU3\")", e.getMessage()); - } - } @Test public void testCreateInvalidParamNoPath() { @@ -155,23 +138,6 @@ public class FhirResourceDaoDstu3SearchCustomSearchParamTest extends BaseJpaDstu } } - @Test - public void testCreateInvalidParamNoResourceName() { - SearchParameter fooSp = new SearchParameter(); - fooSp.addBase("Patient"); - fooSp.setCode("foo"); - fooSp.setType(org.hl7.fhir.dstu3.model.Enumerations.SearchParamType.TOKEN); - fooSp.setTitle("FOO SP"); - fooSp.setExpression("gender"); - fooSp.setXpathUsage(org.hl7.fhir.dstu3.model.SearchParameter.XPathUsageType.NORMAL); - fooSp.setStatus(org.hl7.fhir.dstu3.model.Enumerations.PublicationStatus.ACTIVE); - try { - mySearchParameterDao.create(fooSp, mySrd); - fail(); - } catch (UnprocessableEntityException e) { - assertEquals(Msg.code(1117) + "Invalid SearchParameter.expression value \"gender\". Must start with a resource name.", e.getMessage()); - } - } @Test public void testCreateInvalidParamParamNullStatus() { @@ -322,10 +288,11 @@ public class FhirResourceDaoDstu3SearchCustomSearchParamTest extends BaseJpaDstu mySearchParameterDao.create(threadIdSp, mySrd); fail(); } catch (UnprocessableEntityException e) { - assertThat(e.getMessage(), startsWith(Msg.code(1119) + "The expression \"Communication.payload[1].contentAttachment is not null\" can not be evaluated and may be invalid: ")); + assertThat(e.getMessage(), startsWith(Msg.code(1121) + "Invalid FHIRPath format for SearchParameter.expression \"Communication.payload[1].contentAttachment is not null\": Error at 1, 4: Premature ExpressionNode termination at unexpected token \"null\"")); } } + /** * See #863 */ diff --git a/hapi-fhir-jpaserver-test-dstu3/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderDstu3Test.java b/hapi-fhir-jpaserver-test-dstu3/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderDstu3Test.java index 27c51efc73f..d8e3c5e1d68 100644 --- a/hapi-fhir-jpaserver-test-dstu3/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderDstu3Test.java +++ b/hapi-fhir-jpaserver-test-dstu3/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderDstu3Test.java @@ -5,6 +5,7 @@ import ca.uhn.fhir.jpa.api.config.DaoConfig; import ca.uhn.fhir.jpa.dao.data.ISearchDao; import ca.uhn.fhir.jpa.entity.Search; import ca.uhn.fhir.jpa.search.SearchCoordinatorSvcImpl; +import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; import ca.uhn.fhir.jpa.util.QueryParameterUtils; import ca.uhn.fhir.model.api.TemporalPrecisionEnum; import ca.uhn.fhir.model.primitive.InstantDt; @@ -15,6 +16,7 @@ import ca.uhn.fhir.rest.api.CacheControlDirective; import ca.uhn.fhir.rest.api.Constants; import ca.uhn.fhir.rest.api.MethodOutcome; import ca.uhn.fhir.rest.api.SummaryEnum; +import ca.uhn.fhir.rest.api.server.IBundleProvider; import ca.uhn.fhir.rest.client.api.IClientInterceptor; import ca.uhn.fhir.rest.client.api.IGenericClient; import ca.uhn.fhir.rest.client.api.IHttpRequest; @@ -27,6 +29,7 @@ import ca.uhn.fhir.rest.param.ParamPrefixEnum; import ca.uhn.fhir.rest.param.StringAndListParam; import ca.uhn.fhir.rest.param.StringOrListParam; import ca.uhn.fhir.rest.param.StringParam; +import ca.uhn.fhir.rest.param.TokenParam; import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException; @@ -103,6 +106,7 @@ import org.hl7.fhir.dstu3.model.Organization; import org.hl7.fhir.dstu3.model.Parameters; import org.hl7.fhir.dstu3.model.Patient; import org.hl7.fhir.dstu3.model.Period; +import org.hl7.fhir.dstu3.model.Person; import org.hl7.fhir.dstu3.model.PlanDefinition; import org.hl7.fhir.dstu3.model.Practitioner; import org.hl7.fhir.dstu3.model.ProcedureRequest; @@ -112,6 +116,7 @@ import org.hl7.fhir.dstu3.model.Questionnaire.QuestionnaireItemType; import org.hl7.fhir.dstu3.model.QuestionnaireResponse; import org.hl7.fhir.dstu3.model.Reference; import org.hl7.fhir.dstu3.model.RelatedArtifact; +import org.hl7.fhir.dstu3.model.SearchParameter; import org.hl7.fhir.dstu3.model.StringType; import org.hl7.fhir.dstu3.model.StructureDefinition; import org.hl7.fhir.dstu3.model.Subscription; @@ -151,7 +156,6 @@ import java.util.TreeSet; import java.util.UUID; import java.util.stream.Collectors; -import static ca.uhn.fhir.test.utilities.CustomMatchersUtil.assertDoesNotContainAnyOf; import static org.apache.commons.lang3.StringUtils.isNotBlank; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.contains; @@ -261,6 +265,49 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test { assertEquals(0, returnedBundle.getEntry().size()); } + @Test + public void createResourceSearchParameter_withExpressionMetaSecurity_succeeds(){ + String spCallingName = "securitySP"; + String secCode = "secCode"; + + SearchParameter searchParameter = new SearchParameter(); + searchParameter.setStatus(Enumerations.PublicationStatus.ACTIVE); + searchParameter.setCode(spCallingName); + searchParameter.addBase("Patient").addBase("Account"); + searchParameter.setType(Enumerations.SearchParamType.TOKEN); + searchParameter.setExpression("meta.security"); + + ourClient.create().resource(searchParameter).execute(); + mySearchParamRegistry.forceRefresh(); + + IIdType expectedPatientId = createPatientWithMeta(new Meta().addSecurity(new Coding().setCode(secCode))); + IIdType dontCare = createPatientWithMeta(new Meta().addSecurity(new Coding().setCode("L"))); + + Bundle searchResultBundle = ourClient.search().forResource(Patient.class).where(new StringClientParam(spCallingName).matches().value(secCode)).returnBundle(Bundle.class).execute(); + + List foundPatients = toUnqualifiedVersionlessIdValues(searchResultBundle); + + assertEquals(1, foundPatients.size()); + + assertEquals(foundPatients.get(0), expectedPatientId.getValue()); + + } + + @Test + public void createSearchParameter_with2Expressions_succeeds(){ + SearchParameter searchParameter = new SearchParameter(); + searchParameter.setStatus(Enumerations.PublicationStatus.ACTIVE); + searchParameter.setCode("myGender"); + searchParameter.addBase("Patient").addBase("Person"); + searchParameter.setType(Enumerations.SearchParamType.TOKEN); + searchParameter.setExpression("Patient.gender|Person.gender"); + + MethodOutcome result= ourClient.create().resource(searchParameter).execute(); + + assertEquals(true, result.getCreated()); + + } + @Test public void testSuppressNoExtensibleWarnings() { RequestValidatingInterceptor interceptor = new RequestValidatingInterceptor(); @@ -3178,7 +3225,7 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test { //@formatter:on List patients = toUnqualifiedVersionlessIds(found); assertThat(patients, hasItems(id2)); - assertDoesNotContainAnyOf(patients, List.of(id1a, id1b)); + assertThat(patients, not(hasItems(id1a, id1b))); } { //@formatter:off @@ -3190,7 +3237,7 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test { .execute(); //@formatter:on List patients = toUnqualifiedVersionlessIds(found); - assertThat(patients.toString(), patients, not(hasItem(id2))); + assertThat(patients.toString(), patients, not(hasItems(id2))); assertThat(patients.toString(), patients, (hasItems(id1a, id1b))); } { @@ -3204,7 +3251,7 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test { //@formatter:on List patients = toUnqualifiedVersionlessIds(found); assertThat(patients, (hasItems(id1a, id1b))); - assertThat(patients, not(hasItem(id2))); + assertThat(patients, not(hasItems(id2))); } } @@ -3701,7 +3748,7 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test { List ids = toUnqualifiedVersionlessIdValues(bundle); assertThat(ids, contains(oid1)); - assertThat(ids, not(hasItem(oid2))); + assertThat(ids, not(contains(oid2))); } finally { IOUtils.closeQuietly(resp); } @@ -3888,7 +3935,7 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test { List ids = toUnqualifiedVersionlessIdValues(bundle); assertThat(ids, contains(id1.getValue())); - assertThat(ids, not(hasItem(id2.getValue()))); + assertThat(ids, not(contains(id2.getValue()))); } finally { IOUtils.closeQuietly(resp); } @@ -4781,5 +4828,11 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test { return new InstantDt(theDate).getValueAsString(); } + private IIdType createPatientWithMeta(Meta theMeta){ + + Patient patient = new Patient(); + patient.setMeta(theMeta); + return ourClient.create().resource(patient).execute().getId().toUnqualifiedVersionless(); + } } diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchCustomSearchParamTest.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchCustomSearchParamTest.java index b15f2c21e0d..f51ca64a4e1 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchCustomSearchParamTest.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchCustomSearchParamTest.java @@ -782,7 +782,7 @@ public class FhirResourceDaoR4SearchCustomSearchParamTest extends BaseJpaR4Test mySearchParameterDao.create(threadIdSp, mySrd); fail(); } catch (UnprocessableEntityException e) { - assertThat(e.getMessage(), startsWith(Msg.code(1121) + "Invalid SearchParameter.expression value \"Communication.payload[1].contentAttachment is not null\"")); + assertThat(e.getMessage(), startsWith(Msg.code(1121) + "Invalid FHIRPath format for SearchParameter.expression \"Communication.payload[1].contentAttachment is not null\"")); } } diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoSearchParameterR4Test.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoSearchParameterR4Test.java index 28c2e9dd031..79ae7d6318c 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoSearchParameterR4Test.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoSearchParameterR4Test.java @@ -81,7 +81,7 @@ public class FhirResourceDaoSearchParameterR4Test { myDao.validateResourceForStorage(nextSearchParameter, null); fail(); } catch (UnprocessableEntityException e) { - assertEquals(Msg.code(1121) + "Invalid SearchParameter.expression value \"Patient.ex[[[\": Error in ?? at 1, 1: Found [ expecting a token name", e.getMessage()); + assertEquals(Msg.code(1121) + "Invalid FHIRPath format for SearchParameter.expression \"Patient.ex[[[\": Error in ?? at 1, 1: Found [ expecting a token name", e.getMessage()); } } diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderCustomSearchParamR4Test.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderCustomSearchParamR4Test.java index 4475fb3163f..cf980d8075f 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderCustomSearchParamR4Test.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderCustomSearchParamR4Test.java @@ -141,7 +141,7 @@ public class ResourceProviderCustomSearchParamR4Test extends BaseResourceProvide myClient.create().resource(sp).execute(); fail(); } catch (UnprocessableEntityException e) { - assertEquals("HTTP 422 Unprocessable Entity: " + Msg.code(1120) + "SearchParameter.expression value \"Patient\" is invalid", e.getMessage()); + assertEquals("HTTP 422 Unprocessable Entity: " + Msg.code(1120) + "SearchParameter.expression value \"Patient\" is invalid due to missing/incorrect path", e.getMessage()); } } 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 81efe7fa82c..3075d945d8c 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 @@ -9,6 +9,7 @@ import ca.uhn.fhir.jpa.model.entity.ResourceHistoryTable; import ca.uhn.fhir.jpa.model.util.JpaConstants; import ca.uhn.fhir.jpa.model.util.UcumServiceUtil; import ca.uhn.fhir.jpa.search.SearchCoordinatorSvcImpl; +import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; import ca.uhn.fhir.jpa.term.ZipCollectionBuilder; import ca.uhn.fhir.jpa.test.config.TestR4Config; import ca.uhn.fhir.jpa.util.QueryParameterUtils; @@ -23,6 +24,7 @@ import ca.uhn.fhir.rest.api.MethodOutcome; import ca.uhn.fhir.rest.api.PreferReturnEnum; import ca.uhn.fhir.rest.api.SearchTotalModeEnum; import ca.uhn.fhir.rest.api.SummaryEnum; +import ca.uhn.fhir.rest.api.server.IBundleProvider; import ca.uhn.fhir.rest.client.apache.ResourceEntity; import ca.uhn.fhir.rest.client.api.IClientInterceptor; import ca.uhn.fhir.rest.client.api.IGenericClient; @@ -38,6 +40,7 @@ import ca.uhn.fhir.rest.param.ParamPrefixEnum; import ca.uhn.fhir.rest.param.StringAndListParam; import ca.uhn.fhir.rest.param.StringOrListParam; import ca.uhn.fhir.rest.param.StringParam; +import ca.uhn.fhir.rest.param.TokenParam; import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException; @@ -127,6 +130,7 @@ import org.hl7.fhir.r4.model.Organization; import org.hl7.fhir.r4.model.Parameters; import org.hl7.fhir.r4.model.Patient; import org.hl7.fhir.r4.model.Period; +import org.hl7.fhir.r4.model.Person; import org.hl7.fhir.r4.model.Practitioner; import org.hl7.fhir.r4.model.Procedure; import org.hl7.fhir.r4.model.Quantity; @@ -288,6 +292,41 @@ public class ResourceProviderR4Test extends BaseResourceProviderR4Test { } + @Test + public void createResourceSearchParameter_withExpressionMetaSecurity_succeeds(){ + SearchParameter searchParameter = new SearchParameter(); + searchParameter.setId("resource-security"); + searchParameter.setStatus(Enumerations.PublicationStatus.ACTIVE); + searchParameter.setName("Security"); + searchParameter.setCode("_security"); + searchParameter.addBase("Patient").addBase("Account"); + searchParameter.setType(Enumerations.SearchParamType.TOKEN); + searchParameter.setExpression("meta.security"); + + IIdType id = myClient.update().resource(searchParameter).execute().getId().toUnqualifiedVersionless(); + + assertNotNull(id); + assertEquals("resource-security", id.getIdPart()); + + } + + @Test + public void createSearchParameter_with2Expressions_succeeds(){ + + SearchParameter searchParameter = new SearchParameter(); + + searchParameter.setStatus(Enumerations.PublicationStatus.ACTIVE); + searchParameter.setCode("myGender"); + searchParameter.addBase("Patient").addBase("Person"); + searchParameter.setType(Enumerations.SearchParamType.TOKEN); + searchParameter.setExpression("Patient.gender|Person.gender"); + + MethodOutcome result= myClient.create().resource(searchParameter).execute(); + + assertEquals(true, result.getCreated()); + + } + @Test public void testParameterWithNoValueThrowsError_InvalidRootParam() throws IOException { SearchParameter searchParameter = new SearchParameter();